前言
接上篇设计模式(四):《Head First设计模式》工厂模式之简单工厂
概念
工厂方法模式:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类
抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类
工厂方法
abstract Product factoryMethod(String type)
- 工厂方法是抽象的,所以依赖子类来处理对象的创建
- 必须返回一个产品,比如煎饼果子工厂必须返回煎饼果子
- 参数不是必需的,根据需求来定
煎饼果子干大了
煎饼果子产业逐步扩大,煎饼果子研究室也持续出新品,并且出现地区风味了,但是煎饼的制作工艺和核心配方是一样的。
鉴于上述情况,总工厂负责生产,加盟店负责销售的模式不再适用。
Demo
以下只实现了临沂风味店,菜煎饼店同理~
煎饼果子总店
public abstract class JBGZStore {
public Jianbingguozi orderJBGZ(String type) {
Jianbingguozi jbgz;
jbgz = createJBGZ(type);
jbgz.prepare();
jbgz.make();
jbgz.cut();
return jbgz;
}
// 工厂方法,由子类负责实现
abstract Jianbingguozi createJBGZ(String type);
}
依照总店打造的分店(临沂风味煎饼果子总代理)
public class LinyiStore extends JBGZStore{
@Override
Jianbingguozi createJBGZ(String type) {
Jianbingguozi jianbingguozi = null;
if("乞丐版".equals(type)) {
jianbingguozi = new LYQigaibanJBGZ();
}else if("高配版".equals(type)) {
jianbingguozi = new LYGaopeibanJBGZ();
}else if("豪华版".equals(type)) {
jianbingguozi = new LYHaohuabanJBGZ();
}
return jianbingguozi;
}
}
产品-煎饼果子抽象类
public abstract class Jianbingguozi {
String name;
// 加什么
ArrayList<String> adders = new ArrayList<>(8);
void prepare() {
printf("开始准备制作" + name + "……");
for(int i = 0; i < adders.size();i++) {
printf("放 " + adders.get(i));
}
}
// 正常的煎饼果子制作是一样的
void make() {
printf("制作煎饼");
}
// 是否需要拦腰切断
void cut() {
printf("不需要切开");
}
private void printf(String str) {
System.out.println(str);
}
}
产品实现--临沂风味丐版煎饼果子
public class LYQigaibanJBGZ extends Jianbingguozi{
public LYQigaibanJBGZ() {
name = "临沂风味丐版煎饼果子";
adders.add("鸡蛋");
adders.add("果子");
}
}
产品实现--临沂风味高配版煎饼果子
public class LYGaopeibanJBGZ extends Jianbingguozi{
public LYGaopeibanJBGZ() {
name = "临沂风味高配版煎饼果子";
adders.add("两个鸡蛋");
adders.add("果子");
adders.add("火腿肠");
}
}
产品实现--临沂风味豪华版版煎饼果子
public class LYHaohuabanJBGZ extends Jianbingguozi{
public LYHaohuabanJBGZ() {
name = "临沂风味豪华版煎饼果子";
adders.add("两个鸡蛋");
adders.add("果子");
adders.add("火腿肠");
adders.add("鸡柳");
adders.add("培根");
adders.add("生菜");
}
}
测试
public class JBGZTestDriver {
public static void main(String[] args) {
JBGZStore lyStore = new LinyiStore();
Jianbingguozi lyjbgz = lyStore.createJBGZ("豪华版");
System.out.println("土豪顾客点了个 " + lyjbgz.name);
}
}
Demo解析
跟上一篇文章的区别在于,我们将煎饼果子的制作权利下放到了产品的具体制作商那里了,而不是控制在总工厂,这里用的就是工厂方法模式
定义了一个创建对象的接口JBGZStore
,但是由具体的煎饼果子商店决定要实例化哪个产品
abstract Jianbingguozi createJBGZ(String type);
上面的代码就是工厂方法,是一个抽象方法,具体实现由子类负责。这样就将实例化推迟到了子类当中。
书中是利用Pizza制作解析的,图示如下
工厂方法模式与抽象工厂模式
抽象工厂是创建一个产品家族,而工厂方法创建一个产品
-
创建对象的方法不同
- 工厂方法使用继承。利用工厂方法创建对象,需要扩展一个类,并覆盖它的工厂方法
- 抽象工厂通过对象的组合。抽象工厂提供一个用来创建一个产品家族的抽象类型。这个类型的子类定义了产品被产生的方法。”把一群相关的产品集合起来“
借用下书中的Pizza原料工厂例子,如下
定义抽象接口用来创建产品家族(原料):Interface PizzaIngredientFactory
两个子类(抽象工厂):纽约原料工厂,芝加哥原料工厂
这两个子类负责原料生产,通常是通过工厂方法来实现的所有的原料都是属于产品,正如上述工厂方法中的煎饼果子这个产品