经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
设计模式之工厂模式(上篇)
来源:cnblogs  作者:迷途纸鸢  时间:2019/8/9 8:51:07  对本文有异议

为了面向接口编程,而不是面向实现编程,所以此时我么就不能再直接使用new了,因

为当看到“new”时,我们就会想到“具体”。

下面来看一个例子,假如你有一个披萨店,你的代码可能这么写:

  1. 1 Pizza orderPizza(){
  2. 2 Pizza pizza = new Pizza();
  3. 3
  4. 4 pizza.prepare();
  5. 5 pizza.bake();
  6. 6 pizza.cut();
  7. 7 pizza.box();
  8. 8
  9. 9 return pizza;
  10. 10 }

但是此时你需要更多披萨类型,所以你就要修改代码,如下所示:

  1. 1 Pizza orderPizza(String type){
  2. 2 Pizza pizza = new Pizza();
  3. 3
  4. 4 if (type.equals("cheese")) {
  5. 5 pizza = new CheesePizza();
  6. 6 } else if (type.equals("pepperoni")) {
  7. 7 pizza = new PepperoniPizza();
  8. 8 } else if (type.equals("clam")) {
  9. 9 pizza = new ClamPizza();
  10. 10 } else if (type.equals("veggie")) {
  11. 11 pizza = new VeggiePizza();
  12. 12 }
  13. 13
  14. 14 pizza.prepare();
  15. 15 pizza.bake();
  16. 16 pizza.cut();
  17. 17 pizza.box();
  18. 18
  19. 19 return pizza;
  20. 20 }

但是此时由于产业竞争问题,你想加入一些其他口味的pizza或者删除某几种pizza,那么

你就不得不修改orderPizza(String type)里的4-12行,所以随着时间的推移,这个类就必

须一改再改,这毫无疑问是不好的!所以我们现在来把创建对象的代码封装起来,如下所

示:

 

这时我们称这个新对象(SimplePizzaFactory)为“工厂”,用来处理创建对象的细节。

现在让我们创建一个简单的披萨工厂:

先从工厂本身开始,封装创建对象的代码(SimplePizzaFactory.java)

 

  1. 1 public class SimplePizzaFactory {
  2. 2 public Pizza createPizza(String type) {
  3. 3 Pizza pizza = null;
  4. 4
  5. 5 if (type.equals("cheese")) {
  6. 6 pizza = new CheesePizza();
  7. 7 } else if (type.equals("pepperoni")) {
  8. 8 pizza = new PepperoniPizza();
  9. 9 } else if (type.equals("clam")) {
  10. 10 pizza = new ClamPizza();
  11. 11 } else if (type.equals("veggie")) {
  12. 12 pizza = new VeggiePizza();
  13. 13 }
  14. 14 return pizza;
  15. 15 }
  16. 16 }

 

重做PizzaStore(PizzaStore.java):

  1. 1 public class PizzaStore {
  2. 2 SimplePizzaFactory factory;
  3. 3
  4. 4 public PizzaStore(SimplePizzaFactory factory) {
  5. 5 this.factory = factory;
  6. 6 }
  7. 7
  8. 8 public Pizza orderPizza(String type) {
  9. 9 Pizza pizza;
  10. 10
  11. 11 pizza = factory.createPizza(type);
  12. 12
  13. 13 pizza.prepare();
  14. 14 pizza.bake();
  15. 15 pizza.cut();
  16. 16 pizza.box();
  17. 17
  18. 18 return pizza;
  19. 19 }
  20. 20 }

测试类(Main.java):

  1. 1 public class Main {
  2. 2
  3. 3 public static void main(String[] args) {
  4. 4 SimplePizzaFactory factory = new SimplePizzaFactory();
  5. 5 PizzaStore store = new PizzaStore(factory);
  6. 6
  7. 7 Pizza pizza = store.orderPizza("cheese");
  8. 8 System.out.println("We ordered a " + pizza.getName() + "\n");
  9. 9 System.out.println(pizza);
  10. 10
  11. 11 pizza = store.orderPizza("veggie");
  12. 12 System.out.println("We ordered a " + pizza.getName() + "\n");
  13. 13 System.out.println(pizza);
  14. 14 }
  15. 15 }

结果展示:

好啦,这个示例完成了,这个其实叫做简单工厂,他其实不是一个设计模式,而更像是一

种编程习惯。这里只列举了这个项目的关键代码,至于这个简单工厂的完整代码,读者可

到:https://github.com/Stray-Kite/Design-Pattern/tree/master/src/headfirst/designpatterns/factory/pizzas

下载

 

好了,下载聊完了简单工厂,那么让我们进入正题,聊一聊两个重量级的模式,他们都是

工厂!

 

现在我们要建立几个加盟店。

有了这个图,你开始有一个想法啦,那就是:

 

  1. 1 NYPizzaFactory nyFactory = new NYPizzaFactory();
  2. 2 PizzaStore nyStore = new PizzaStore(nyFactory);
  3. 3 nyStore.orderPizza("Veggie");
  4. 4
  5. 5 ChicagePizzaFactory chicageFactory = new ChicagePizzaFactory();
  6. 6 PizzaStore chicageStore = new PizzaStore(chicagoFactory);
  7. 7 chicagoStore.orderPizza("Veggie");

 

但是,你想要多一些质量控制:在推广SimpleFactory时,你发现加盟店的确是采用你的工

厂创建披萨,但是其他部分,却开始采用他们自创的流程:烘烤的做法有些差异、不要切片

、使用其他厂商的盒子。

再想想这个问题,你真的希望能够建立一个框架,把加盟店和创建披萨捆绑在一起的同时又

保持一定的弹性。

 

所以开始使用框架啦:

首先,看看PizzaStore(PizzaStore.java)所做的改变;喔嚯,变成抽象的了,也就是把创

建对象的工作移交给子类做决定了:

  1. 1 public abstract class PizzaStore {
  2. 2 abstract Pizza createPizza(String item);
  3. 3
  4. 4 public Pizza orderPizza(String type) {
  5. 5 Pizza pizza = createPizza(type);
  6. 6 System.out.println("--- Making a " + pizza.getName() + " ---");
  7. 7 pizza.prepare();
  8. 8 pizza.bake();
  9. 9 pizza.cut();
  10. 10 pizza.box();
  11. 11 return pizza;
  12. 12 }
  13. 13 }

接下来,轮到子类给PizzaStore做决定了!(NYPizzaStore.java和ChicagePizzaStore.java

,这是两个披萨店):

  1. 1 public class ChicagoPizzaStore extends PizzaStore {
  2. 2 Pizza createPizza(String item) {
  3. 3 if (item.equals("cheese")) {
  4. 4 return new ChicagoStyleCheesePizza();
  5. 5 } else if (item.equals("veggie")) {
  6. 6 return new ChicagoStyleVeggiePizza();
  7. 7 } else if (item.equals("clam")) {
  8. 8 return new ChicagoStyleClamPizza();
  9. 9 } else if (item.equals("pepperoni")) {
  10. 10 return new ChicagoStylePepperoniPizza();
  11. 11 } else return null;
  12. 12 }
  13. 13 }
  1. 1 public class NYPizzaStore extends PizzaStore{
  2. 2 Pizza createPizza(String item) {
  3. 3 if (item.equals("cheese")) {
  4. 4 return new NYStyleCheesePizza();
  5. 5 } else if (item.equals("veggie")) {
  6. 6 return new NYStyleVeggiePizza();
  7. 7 } else if (item.equals("clam")) {
  8. 8 return new NYStyleClamPizza();
  9. 9 } else if (item.equals("pepperoni")) {
  10. 10 return new NYStylePepperoniPizza();
  11. 11 } else return null;
  12. 12 }
  13. 13 }

差点忘记了,我们还得写一个比萨本身(Pizza.java):

  1. 1 import java.util.ArrayList;
  2. 2
  3. 3 public abstract class Pizza {
  4. 4 String name;
  5. 5 String dough;
  6. 6 String sauce;
  7. 7 ArrayList<String> toppings = new ArrayList<String>();
  8. 8
  9. 9 void prepare() {
  10. 10 System.out.println("Prepare " + name);
  11. 11 System.out.println("Tossing dough...");
  12. 12 System.out.println("Adding sauce...");
  13. 13 System.out.println("Adding toppings: ");
  14. 14 for (String topping : toppings) {
  15. 15 System.out.println(" " + topping);
  16. 16 }
  17. 17 }
  18. 18
  19. 19 void bake() {
  20. 20 System.out.println("Bake for 25 minutes at 350");
  21. 21 }
  22. 22
  23. 23 void cut() {
  24. 24 System.out.println("Cut the pizza into diagonal slices");
  25. 25 }
  26. 26
  27. 27 void box() {
  28. 28 System.out.println("Place pizza in official PizzaStore box");
  29. 29 }
  30. 30
  31. 31 public String getName() {
  32. 32 return name;
  33. 33 }
  34. 34
  35. 35 public String toString() {
  36. 36 StringBuffer display = new StringBuffer();
  37. 37 display.append("---- " + name + " ----\n");
  38. 38 display.append(dough + "\n");
  39. 39 display.append(sauce + "\n");
  40. 40 for (String topping : toppings) {
  41. 41 display.append(topping + "\n");
  42. 42 }
  43. 43 return display.toString();
  44. 44 }
  45. 45 }

然后还剩下,一些具体的子类:定义两个不同的店的芝士披萨

NYStyleCheesePizza.java:

  1. 1 public class NYStyleCheesePizza extends Pizza {
  2. 2 public NYStyleCheesePizza() {
  3. 3 name = "NY Style Sauce and Cheese Pizza";
  4. 4 dough = "Thin Crust Dough";
  5. 5 sauce = "Marinara Sauce";
  6. 6
  7. 7 toppings.add("Grated Reggiano Cheese");
  8. 8 }
  9. 9 }

ChicagoStyleCheesePizza.java:

  1. 1 public class ChicagoStyleCheesePizza extends Pizza {
  2. 2 public ChicagoStyleCheesePizza() {
  3. 3 name = "Chicago Style Deep Dish Cheese Pizza";
  4. 4 dough = "Extra Thick Crust Dough";
  5. 5 sauce = "Plum Tomato Sauce";
  6. 6
  7. 7 toppings.add("Shredded Mozzarella Cheese");
  8. 8 }
  9. 9
  10. 10 void cut() {
  11. 11 System.out.println("Cutting the pizza into square slices");
  12. 12 }
  13. 13 }

 

最后来一组测试类(Main.java):

  1. 1 public class Main {
  2. 2
  3. 3 public static void main(String[] args) {
  4. 4 PizzaStore nyStore = new NYPizzaStore();
  5. 5 PizzaStore chicagoStore = new ChicagoPizzaStore();
  6. 6
  7. 7 Pizza pizza = nyStore.orderPizza("cheese");
  8. 8 System.out.println("Ethan ordered a " + pizza.getName() + "\n");
  9. 9
  10. 10 pizza = chicagoStore.orderPizza("cheese");
  11. 11 System.out.println("Joel ordered a " + pizza.getName() + "\n");
  12. 12
  13. 13 pizza = nyStore.orderPizza("clam");
  14. 14 System.out.println("Ethan ordered a " + pizza.getName() + "\n");
  15. 15
  16. 16 pizza = chicagoStore.orderPizza("clam");
  17. 17 System.out.println("Joel ordered a " + pizza.getName() + "\n");
  18. 18
  19. 19 pizza = nyStore.orderPizza("pepperoni");
  20. 20 System.out.println("Ethan ordered a " + pizza.getName() + "\n");
  21. 21
  22. 22 pizza = chicagoStore.orderPizza("pepperoni");
  23. 23 System.out.println("Joel ordered a " + pizza.getName() + "\n");
  24. 24
  25. 25 pizza = nyStore.orderPizza("veggie");
  26. 26 System.out.println("Ethan ordered a " + pizza.getName() + "\n");
  27. 27
  28. 28 pizza = chicagoStore.orderPizza("veggie");
  29. 29 System.out.println("Joel ordered a " + pizza.getName() + "\n");
  30. 30 }
  31. 31 }

 

结果展示(部分结果)

 

此段代码地址:

          https://github.com/Stray-Kite/Design-Pattern/tree/master/src/headfirst/designpatterns/factory/pizzafm

好了,现在然我们看一下工厂模式的定义吧!

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

实例化推迟到了子类。

重点:简单工厂和工厂方法的区别:

                 子类的确看起来很像简单工厂。简单工程把全部的事情,在一个地方都处理完了,然而工厂方

          法却是创建了一个框架,让子类决定要如何实现。比方说,在工厂方法中,orderPizza()方法提供了

          一个一般的框架,以便创建披萨,orderPizza()方法依赖工厂方法创建具体类,并制造出实际的披萨

          。可通过继承PizzaStore()类,决定实际制造出的披萨是什么。简单工厂的做法,可以将对象创建封

          装起来,但是简单工厂不具备工厂方法的弹性,因为简单工程不能变更正在创建的产品。

未完待续......

 

原文链接:http://www.cnblogs.com/Trojan00/p/11320794.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号