工厂方法模式
定义创建对象的接口(或抽象类),让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类进行。
分析实现步骤
类图
- 创建抽象类(不变)
- 创建地域特色的产品类
- 创建工厂方法
- 创建子类实现工厂方法
- 客户端测试
- 分析
代码实现
创建地域特色的产品类
/*** 中国奶油蛋糕*/public class CNCreamCake extends AbstractCake {@Overridepublic void prepare() {System.out.println("原料:原胚、奶油、中国元素");}}
/*** 中国水果蛋糕*/public class CNfruitCake extends AbstractCake {@Overridepublic void prepare() {System.out.println("原料:原胚、水果、中国元素");}}
/*** 美国奶油蛋糕*/public class USCreamCake extends AbstractCake {@Overridepublic void prepare() {System.out.println("原料:原胚、奶油、美国元素");}}
/*** 美国水果蛋糕*/public class USfruitCake extends AbstractCake {@Overridepublic void prepare() {System.out.println("原料:原胚、水果、美国元素");}}
创建工厂方法
/*** 工厂方法,有方法,但不实现,下放到子类去执行*/public abstract class FactoryMethod {//定义一个抽象方法,让各个工厂子类自己实现abstract AbstractCake createCake(String orderType);public FactoryMethod() {AbstractCake cake;String orderType;do {orderType = getType();//获取简单(静态)工厂cake = createCake(orderType);if(cake != null) {cake.prepare();cake.bake();cake.box();cake.send();} else {System.out.println("预定失败");break;}}while(true);}//输入蛋糕类型private String getType() {try {BufferedReader strin = new BufferedReader(new InputStreamReader(System.in));System.out.println("请输入蛋糕类型:");return strin.readLine();} catch (IOException e) {e.printStackTrace();return "";}}}
创建子类实现工厂方法
/*** 子类实现(中国)工厂方法*/public class CNOrderCake extends FactoryMethod{@OverrideAbstractCake createCake(String orderType) {AbstractCake cake = null;if (orderType.equals("水果")) {cake = new CNfruitCake();cake.setName(orderType + "蛋糕(中国味道)");} else if (orderType.equals("奶油")) {cake = new CNCreamCake();cake.setName(orderType + "蛋糕(中国味道)");} else {System.out.println("暂不支持的蛋糕类型");return cake;}return cake;}}
/*** 子类实现(美国)工厂方法*/public class USOrderCake extends FactoryMethod{@OverrideAbstractCake createCake(String orderType) {AbstractCake cake = null;if (orderType.equals("水果")) {cake = new USfruitCake();cake.setName(orderType + "蛋糕(美国味道)");} else if (orderType.equals("奶油")) {cake = new USCreamCake();cake.setName(orderType + "蛋糕(美国味道)");} else {System.out.println("暂不支持的蛋糕类型");return cake;}return cake;}}
客户端测试
public class CakeStore {public static void main(String[] args) {//中国new CNOrderCake();//美国// new USOrderCake();}}//测试结果请输入蛋糕类型:水果原料:原胚、水果、中国元素水果蛋糕(中国味道)烘焙;水果蛋糕(中国味道)包装;水果蛋糕(中国味道)配送;请输入蛋糕类型:巧克力暂不支持的蛋糕类型预定失败
分析
由上代码可知,此时如果新增一个英国口味的各种蛋糕,则继承通用工厂方法,新增一个定制的子类预定类的实现,以及新增对应的类型的蛋糕实现。确实有很好的OCP,但是有没有觉得很复杂,新建的类有点多,感觉还不如简单方法细化蛋糕类(TODO 可能境界没有达到,后面再体会一下)。
框架或项目源码分析
应用场景
- 客户只知道创建产品的工厂名,而不知道具体的产品名
- 创建对象的任务由多个具体子工厂中的某一个完成,而抽象工厂只提供创建产品的接口
- 客户不关心创建产品的细节,只关心产品的品牌
