设计模式读书笔记-----工厂方法模式
来源:互联网 发布:淘宝助理不能图片搬家 编辑:程序博客网 时间:2024/06/02 10:13
一、问题
在前一章《设计模式读书笔记-----简单工厂模式》中通过披萨的实例介绍了简单工厂模式。在披萨实例中,如果我想根据地域的不同生产出不同口味的披萨,如纽约口味披萨,芝加哥口味披萨。如果利用简单工厂模式,我们需要两个不同的工厂,NYPizzaFactory、ChicagoPizzaFactory。在该地域中有很多的披萨店,他们并不想依照总店的制作流程来生成披萨,而是希望采用他们自己的制作流程。这个时候如果还使用简单工厂模式,因为简单工厂模式是将披萨的制作流程完全承包了。那么怎么办?
二、解决方案
我们可以这样解决:将披萨的制作方法交给各个披萨店完成,但是他们只能提供制作完成的披萨,披萨的订单处理仍然要交给披萨工厂去做。也就是说,我们将createPizza()方法放回到PizzaStore中,其他的部分还是保持不变。
三、基本定义
工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法模式让实例化推迟到子类。
四、模式结构
工厂方法模式的UML结构图:
Product:抽象产品。所有的产品必须实现这个共同的接口,这样一来,使用这些产品的类既可以引用这个接口。而不是具体类。
ConcreteProduct:具体产品。
Creator:抽象工厂。它实现了所有操纵产品的方法,但不实现工厂方法。Creator所有的子类都必须要实现factoryMethod()方法。
ConcreteCreator:具体工厂。制造产品的实际工厂。它负责创建一个或者多个具体产品,只有ConcreteCreator类知道如何创建这些产品。
工厂方法模式是简单工厂模式的延伸。在工厂方法模式中,核心工厂类不在负责产品的创建,而是将具体的创建工作交给子类去完成。也就是后所这个核心工厂仅仅只是提供创建的接口,具体实现方法交给继承它的子类去完成。当我们的系统需要增加其他新的对象时,我们只需要添加一个具体的产品和它的创建工厂即可,不需要对原工厂进行任何修改,这样很好地符合了“开闭原则”。
五、工厂方法模式实现
针对上面的解决方案,得到如下UML结构图:
抽象产品类:Pizza.java
1 public abstract class Pizza { 2 protected String name; //名称 3 protected String dough; //面团 4 protected String sause; //酱料 5 protected List<String> toppings = new ArrayList<String>(); //佐料 6 7 8 public void prepare() { 9 System.out.println("Preparing "+name);10 System.out.println("Tossing dough");11 System.out.println("Adding sause");12 System.out.println("Adding toppings");13 for(int i = 0;i < toppings.size();i++){14 System.out.println(" "+toppings.get(i));15 }16 }17 18 public void bake() {19 System.out.println("Bake for 25 minutes at 350");20 }21 22 public void cut() {23 System.out.println("Cutting the pizza into diagonal slices");24 }25 26 public void box() {27 System.out.println("Place pizza in official PizzaStore box");28 }29 30 public String getName(){31 return name;32 }33 }
具体产品类:NYStyleCheesePizza.java
1 public class NYStyleCheesePizza extends Pizza{ 2 public NYStyleCheesePizza(){ 3 name = "Ny Style Sauce and Cheese Pizza"; 4 dough = "Thin Crust Dough"; 5 sause = "Marinara Sauce"; 6 7 toppings.add("Crated Reggiano Cheese"); 8 } 9 10 }
ChicagoStyleCheesePizza.java
1 public class ChicagoStyleCheesePizza extends Pizza { 2 public ChicagoStyleCheesePizza(){ 3 name = "Chicago Style Deep Dish Cheese Pizza"; 4 dough = "Extra Thick Crust Dough"; 5 sause = "Plum Tomato Sauce"; 6 7 toppings.add("Shredded Mozzarella Cheese"); 8 } 9 10 public void cut(){11 System.out.println("Cutting the Pizza into square slices");12 }13 }
抽象工厂:披萨总店。PizzaStore.java
1 public abstract class PizzaStore { 2 public Pizza orderPizza(String type){ 3 Pizza pizza; 4 pizza = createPizza(type); 5 6 pizza.prepare(); 7 pizza.bake(); 8 pizza.cut(); 9 pizza.box();10 11 return pizza;12 }13 14 /*15 * 创建pizza的方法交给子类去实现16 */17 abstract Pizza createPizza(String type);18 }
具体工厂。披萨分店。NYPizzaStore.java
1 public class NYPizzaStore extends PizzaStore{ 2 3 @Override 4 Pizza createPizza(String item) { 5 Pizza pizza = null; 6 if("cheese".equals(item)){ 7 pizza = new NYStyleCheesePizza(); 8 } 9 else if("veggie".equals(item)){10 pizza = new NYStyleVeggiePizza();11 }12 else if("clam".equals(item)){13 pizza = new NYStyleClamPizza();14 }15 else if("pepperoni".equals(item)){16 pizza = new NYStylePepperoniPizza();17 }18 19 return pizza;20 }
ChicagoPizzaStore.java
1 public class ChicagoPizzaStore extends PizzaStore { 2 Pizza createPizza(String type) { 3 Pizza pizza = null; 4 if("cheese".equals(type)){ 5 pizza = new ChicagoStyleCheesePizza(); 6 } 7 else if("clam".equals(type)){ 8 pizza = new ChicagoStyleClamPizza(); 9 }10 else if("pepperoni".equals(type)) {11 pizza = new ChicagoStylePepperoniPizza();12 }13 else if("veggie".equals(type)){14 pizza = new ChicagoStyleVeggiePizza();15 }16 return pizza;17 }18 19 }
做了这么多,应该可以吃披萨了吧。Ethan要一份纽约口味的披萨,Joel需要芝加哥口味的披萨。
PizzaTestDrive.java
1 public class PizzaTestDrive { 2 public static void main(String[] args) { 3 System.out.println("---------Joel 需要的芝加哥的深盘披萨---------"); 4 ChicagoPizzaStore chicagoPizzaStore = new ChicagoPizzaStore(); //建立芝加哥的披萨店 5 Pizza joelPizza =chicagoPizzaStore.orderPizza("cheese"); //下订单 6 System.out.println("Joel ordered a " + joelPizza.getName() + "\n"); 7 8 System.out.println("---------Ethan 需要的纽约风味的披萨---------"); 9 NYPizzaStore nyPizzaStore = new NYPizzaStore();10 Pizza ethanPizza = nyPizzaStore.orderPizza("cheese");11 System.out.println("Ethan ordered a " + ethanPizza.getName() + "\n");12 13 }14 }
运行结果。
六、工厂方法模式的优缺点
优点
1、 在工厂方法中,用户只需要知道所要产品的具体工厂,无须关系具体的创建过程,甚至不需要具体产品类的类名。
2、 在系统增加新的产品时,我们只需要添加一个具体产品类和对应的实现工厂,无需对原工厂进行任何修改,很好地符合了“开闭原则”。
缺点
1、 每次增加一个产品时,都需要增加一个具体类和对象实现工厂,是的系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。
七、工厂方法适用场景
1、一个类不知道它所需要的对象的类。在工厂方法模式中,我们不需要具体产品的类名,我们只需要知道创建它的具体工厂即可。
2、一个类通过其子类来指定创建那个对象。在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。
3、将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定。
七、总结
1、工厂方法模式完全符合“开闭原则”。
2、工厂方法模式使用继承,将对象的创建委托给子类,通过子类实现工厂方法来创建对象。
3、工厂方法允许类将实例化延伸到子类进行。
4、工厂方法让子类决定要实例化的类时哪一个。在这里我们要明白这并不是工厂来决定生成哪种产品,而是在编写创建者类时,不需要知道实际创建的产品是哪个,选择了使用哪个子类,就已经决定了实际创建的产品时哪个了。
5、在工厂方法模式中,创建者通常会包含依赖于抽象产品的代码,而这些抽象产品是、由子类创建的,创建者不需要真的知道在制作哪种具体产品。
- 设计模式读书笔记-----工厂方法模式
- 设计模式读书笔记-----工厂方法模式
- 设计模式读书笔记-----工厂方法模式
- 设计模式读书笔记-----工厂方法模式
- 大话设计模式读书笔记之工厂方法
- 6.java设计模式(读书笔记)简单工厂模式、工厂方法模式、抽象工厂模式
- 读书笔记--工厂方法模式
- 设计模式读书笔记(五)——工厂方法模式
- 设计模式读书笔记之工厂方法模式(Factory method)
- 读书笔记系列2:大话设计模式 -- 工厂方法模式
- 《读书笔记》设计模式——工厂方法模式
- 《大话设计模式》读书笔记6 工厂方法模式
- 设计模式读书笔记之工厂方法模式(Factory method)
- Android设计模式读书笔记——工厂方法模式
- 读书笔记-设计模式(二)之工厂方法模式
- 《设计模式之禅》读书笔记(二)之工厂方法模式
- 设计模式--工厂方法
- 工厂方法设计模式
- 通过xpath查找指定的节点
- FSDataOutputStream中的hsync()不起作用?
- ubuntu 14.04
- 在 Hibernate 中直接操作 JDBC 接口
- 347. Top K Frequent Elements
- 设计模式读书笔记-----工厂方法模式
- 347. Top K Frequent Elements【M】【VIP】【字典排序】
- 仿酷狗音乐列表点击item子控件展开功能
- 详解eclipse插件findbugs新规则的开发过程
- 巧用ViewPager 打造不一样的广告轮播切换效果
- android studio 更改项目包名
- MFC文件打开、保存对话框 及文件创建、存储
- WPF 实现3维视频凸面墙
- 设计模式读书笔记-----抽象工厂模式