1. 首页
  2. 设计模式笔记

04、设计模式笔记—–工厂方法模式

原文出处:http://cmsblogs.com/chenssy


一、问题 

在前一章《设计模式读书笔记—–简单工厂模式》中通过披萨的实例介绍了简单工厂模式。在披萨实例中,如果我想根据地域的不同生产出不同口味的披萨,如纽约口味披萨,芝加哥口味披萨。如果利用简单工厂模式,我们需要两个不同的工厂,NYPizzaFactory、ChicagoPizzaFactory。在该地域中有很多的披萨店,他们并不想依照总店的制作流程来生成披萨,而是希望采用他们自己的制作流程。这个时候如果还使用简单工厂模式,因为简单工厂模式是将披萨的制作流程完全承包了。那么怎么办?

二、解决方案  

我们可以这样解决:将披萨的制作方法交给各个披萨店完成,但是他们只能提供制作完成的披萨,披萨的订单处理仍然要交给披萨工厂去做。也就是说,我们将createPizza()方法放回到PizzaStore中,其他的部分还是保持不变。

三、基本定义  

工厂方法模式定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法模式让实例化推迟到子类。

四、模式结构   

工厂方法模式的UML结构图:

4、设计模式笔记-----工厂方法模式"

  • Product:抽象产品。所有的产品必须实现这个共同的接口,这样一来,使用这些产品的类既可以引用这个接口。而不是具体类。
  • ConcreteProduct:具体产品。
  • Creator:抽象工厂。它实现了所有操纵产品的方法,但不实现工厂方法。Creator所有的子类都必须要实现factoryMethod()方法。
  • ConcreteCreator:具体工厂。制造产品的实际工厂。它负责创建一个或者多个具体产品,只有ConcreteCreator类知道如何创建这些产品。

工厂方法模式是简单工厂模式的延伸。在工厂方法模式中,核心工厂类不在负责产品的创建,而是将具体的创建工作交给子类去完成。也就是后所这个核心工厂仅仅只是提供创建的接口,具体实现方法交给继承它的子类去完成。当我们的系统需要增加其他新的对象时,我们只需要添加一个具体的产品和它的创建工厂即可,不需要对原工厂进行任何修改,这样很好地符合了“开闭原则”。

五、工厂方法模式实现 

针对上面的解决方案,得到如下UML结构图:

4、设计模式笔记-----工厂方法模式"

抽象产品类: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 }

运行结果。

4、设计模式笔记-----工厂方法模式" 

六、工厂方法模式的优缺点  

优点

  • 1、  在工厂方法中,用户只需要知道所要产品的具体工厂,无须关系具体的创建过程,甚至不需要具体产品类的类名。
  • 2、  在系统增加新的产品时,我们只需要添加一个具体产品类和对应的实现工厂,无需对原工厂进行任何修改,很好地符合了“开闭原则”。

缺点

  • 1、  每次增加一个产品时,都需要增加一个具体类和对象实现工厂,是的系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。

七、工厂方法适用场景  

  • 1、一个类不知道它所需要的对象的类。在工厂方法模式中,我们不需要具体产品的类名,我们只需要知道创建它的具体工厂即可。
  • 2、一个类通过其子类来指定创建那个对象。在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。
  • 3、将创建对象的任务委托给多个工厂子类中的某一个,客户端在使用时可以无须关心是哪一个工厂子类创建产品子类,需要时再动态指定。

八、总结  

  • 1、工厂方法模式完全符合“开闭原则”。
  • 2、工厂方法模式使用继承,将对象的创建委托给子类,通过子类实现工厂方法来创建对象。
  • 3、工厂方法允许类将实例化延伸到子类进行。
  • 4、工厂方法让子类决定要实例化的类时哪一个。在这里我们要明白这并不是工厂来决定生成哪种产品,而是在编写创建者类时,不需要知道实际创建的产品是哪个,选择了使用哪个子类,就已经决定了实际创建的产品时哪个了。
  • 5、在工厂方法模式中,创建者通常会包含依赖于抽象产品的代码,而这些抽象产品是、由子类创建的,创建者不需要真的知道在制作哪种具体产品。

希望读者能够给小编留言,也可以点击[此处扫下面二维码关注微信公众号](https://www.ycbbs.vip/?p=28 "此处扫下面二维码关注微信公众号")

看完两件小事

如果你觉得这篇文章对你挺有启发,我想请你帮我两个小忙:

  1. 关注我们的 GitHub 博客,让我们成为长期关系
  2. 把这篇文章分享给你的朋友 / 交流群,让更多的人看到,一起进步,一起成长!
  3. 关注公众号 「方志朋」,公众号后台回复「666」 免费领取我精心整理的进阶资源教程
  4. JS中文网,Javascriptc中文网是中国领先的新一代开发者社区和专业的技术媒体,一个帮助开发者成长的社区,是给开发者用的 Hacker News,技术文章由为你筛选出最优质的干货,其中包括:Android、iOS、前端、后端等方面的内容。目前已经覆盖和服务了超过 300 万开发者,你每天都可以在这里找到技术世界的头条内容。

    本文著作权归作者所有,如若转载,请注明出处

    转载请注明:文章转载自「 Java极客技术学习 」https://www.javajike.com

    标题:04、设计模式笔记—–工厂方法模式

    链接:https://www.javajike.com/article/2402.html

« 05、设计模式笔记—–抽象工厂模式
03、设计模式笔记—–简单工厂模式»

相关推荐

QR code