文章目录
- 1. 定义
- 2. 类图
- 3. Java实现案例
- 3.1 抽象类:Pizza和PizzaStore
- 3.2 具体披萨:北京两种上海两种共四种
- 3.3 具体披萨店:北京店和上海店
- 3.4 测试主方法
工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类的实例化推迟到子类。
2. 类图- 所以具体产品必须实现一个共同的Product接口(抽象类)
- Creator是一个抽象类,它实现了所有到操作产品的方法,但不实现工厂方法factoryMethod
- ConcreteCreator负责创建一个或多个具体Product
- 工厂方法主要用来处理对象的创建,并将创建对象的行为封装在子类中
这里遵循依赖倒置的原则:要依赖抽象,不要依赖具体类
注意⚠️:在设计模式中,“实现一个接口”不一定就是指“写一个类,并利用implement关键词来实现某个java接口”,“实现一个接口”泛指实现某个超类型(类或者接口)的某个方法
3. Java实现案例场景:
- 披萨店生产披萨
- 披萨有相同的处理流程,但有不同的处理方法,比如披萨都需要烘烤,但不同的披萨也许有不同的烘烤温度要求
- 不同的披萨店能制作的披萨类型也不同
- 易于扩展,增加新类型的披萨或新的披萨店
思考准备:
- 根据工厂方法的类图,Product即为披萨、Creator即为披萨店,因此设计抽象Class:披萨、披萨店
- 根据“工厂方法主要用来处理对象的创建,并将创建对象的行为封装在子类中”,我们需要在抽象Creator中设计抽象创建披萨店方法,并由继承它的子类进行具体实现
- 易于扩展,具体披萨类继承抽象披萨类、具体披萨店类继承抽象披萨店类。
Pizza:
package Factory; import java.util.ArrayList; public abstract class Pizza { String name; // 名称 String dough; // 面团类型 String sauce; // 酱料类型 ArrayList toppings = new ArrayList(); // 一套装饰品佐料 // 准备 void prepare(){ System.out.println("Preparing " + name); System.out.println("Tossing dough.."); System.out.println("Adding sauce.."); System.out.println("Adding toppings:"); for(int i = 0; i < toppings.size(); i++){ System.out.println(" " + toppings.get(i)); } } // 烘焙 void bake(){ System.out.println("Bake for 30 min at 360"); } // 分切 void cut(){ System.out.println("Cutting the pizza into diagonal slices"); } // 打包 void box(){ System.out.println("Place pizza in official PizzaStore box"); } public String getName(){ return name; } }
PizzaStore:
package Factory; public abstract class PizzaStore { public Pizza orderPizza(String type){ Pizza pizza; // 创建披萨 pizza = createPizza(type); // 制作披萨并打包 pizza.prepare(); pizza.bake(); pizza.cut(); pizza.box(); // 返回披萨 return pizza; } protected abstract Pizza createPizza(String type); }3.2 具体披萨:北京两种上海两种共四种
北京披萨1
package Factory; public class BjStyleCheesePizza extends Pizza { public BjStyleCheesePizza(){ name = "BeiJing Cheese Pizza"; dough = "Thin Curst Dough"; sauce = "LaoGanMa Sauce"; toppings.add("Grated Reggiano Cheese"); } }
北京披萨2
package Factory; public class BjStyleVeggiePizza extends Pizza { public BjStyleVeggiePizza(){ name = "BeiJing Veggie Pizza"; dough = "Bj2 Dough"; sauce = "Bj2 Sauce"; toppings.add("Bj2 Cheese"); } // 这个北京披萨覆盖了cut方法,将披萨切成正方形 @Override void cut() { System.out.println("Cutting the pizza into square slices"); } }
上海披萨1
package Factory; public class ShStyleCheesePizza extends Pizza { public ShStyleCheesePizza(){ name = "Shanghai Veggie Pizza"; dough = "Sh2 Dough"; sauce = "Sh2 Sauce"; toppings.add("Sh2 Cheese"); } }
上海披萨2
package Factory; public class ShStyleVeggiePizza extends Pizza { public ShStyleVeggiePizza(){ name = "Shanghai Veggie Pizza"; dough = "Sh2 Dough"; sauce = "Sh2 Sauce"; toppings.add("Sh2 Cheese"); } }3.3 具体披萨店:北京店和上海店
工厂方法主要用来处理对象的创建,并将创建对象的行为封装在子类中。在本Demo中“创建对象的行为”即具体类中的createPizza方法。
北京店能生产北京的两种披萨
package Factory; public class BeiJingPizzaStore extends PizzaStore{ @Override protected Pizza createPizza(String type) { if (type.equals("cheese")){ return new BjStyleCheesePizza(); } else if (type.equals("veggie")) { return new BjStyleVeggiePizza(); } // 等等其他类型的上海披萨 return null; } }
同理,上海店能生产上海店两种披萨
package Factory; public class ShangHaiPizzaStore extends PizzaStore{ @Override protected Pizza createPizza(String type) { if (type.equals("cheese")){ return new ShStyleCheesePizza(); } else if (type.equals("veggie")) { return new ShStyleVeggiePizza(); } // 等等其他类型的上海披萨 return null; } }3.4 测试主方法
package Factory; public class MainPizzaTest { public static void main(String[] args) { PizzaStore pizzaStore1 = new BeiJingPizzaStore(); // 北京披萨店 Pizza cheeseFormBj = pizzaStore1.orderPizza("cheese"); // 点一份cheese System.out.println(cheeseFormBj.getName()); // 其他同上,如预定上海披萨店的Veggie披萨 } }
输出:
代码结构:
参考文献:《Head First设计模式(中文版)》弗里曼