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

今天我们来讲一讲抽象工厂:

重要涉及原则:要依赖抽象,不要依赖具体

首先我们需要了解一个设计原则——依赖倒置原则:减少对具体的依赖,所谓的倒置是倒置的

                                                                               仅仅是指的和一般OO设计的思考方式完

                                                                               全相反(不能让高层组件依赖底层组件,

                                                                               而且,不管高层组件还是底层组件,“

                                                                               两者”都应该依赖于抽象)

你应该还没有完全理解这个原则,现在来举个例子加深理解:

 

那么此时,让我们看一下对象依赖关系:

 

上面那个是没有使用依赖倒置原则的,下面来看使用了依赖倒置原则的:

 

此时此刻我们注意到,高层组件(PizzaStore)和底层组件(这些披萨)都依赖Pizza抽象,即

遵循了依赖倒置原则。现在我们解释:不能让高层组件依赖底层组件,而且,不管高层组件还是

底层组件,“两者”都应该依赖于抽象.现在PizzsStore(高层组件)和那些披萨实现类(底层

组件)都依赖于一个抽象类Pizza。

那么如何在设计中遵循依赖倒置原则嘞(下面只是一些建议,再具体项目中不一定都要遵循,

因为如果你想都遵循,可能你连一个简单的程序都写不出来了):

              ①变量不可以持有具体类的引用(如果使用new,就会持有具体类的引用。你可以改

                 用工厂来避开这样的说法);

              ②不要让类派生自具体类(如果派生自具体类,你就会依赖具体类。请派生一个抽象)

              ③不要覆盖基类中意实现的方法(如果覆盖基类已实现的方法,那么你的基类就不是

                  一个真正适合被继承的抽象。基类中已实现的方法,应该有所有的子类共享)。

 

现在让我们回到我们的披萨店

建造原料工厂:

 

  1. 1 public interface PizzaIngredientFactory {
  2. 2
  3. 3 public Dough createDough();
  4. 4 public Sauce createSauce();
  5. 5 public Cheese createCheese();
  6. 6 public Veggies[] createVeggies();
  7. 7 public Pepperoni createPepperoni();
  8. 8 public Clams createClam();
  9. 9
  10. 10 }

 

现在我们有不同地方的原料工厂,他们都要实现原料工厂这一个接口:

纽约原料工厂:

  1. 1 public class NYPizzaIngredientFactory implements PizzaIngredientFactory {
  2. 2
  3. 3 public Dough createDough() {
  4. 4 return new ThinCrustDough();
  5. 5 }
  6. 6
  7. 7 public Sauce createSauce() {
  8. 8 return new MarinaraSauce();
  9. 9 }
  10. 10
  11. 11 public Cheese createCheese() {
  12. 12 return new ReggianoCheese();
  13. 13 }
  14. 14
  15. 15 public Veggies[] createVeggies() {
  16. 16 Veggies veggies[] = { new Garlic(), new Onion(), new Mushroom(), new RedPepper() };
  17. 17 return veggies;
  18. 18 }
  19. 19
  20. 20 public Pepperoni createPepperoni() {
  21. 21 return new SlicedPepperoni();
  22. 22 }
  23. 23
  24. 24 public Clams createClam() {
  25. 25 return new FreshClams();
  26. 26 }
  27. 27 }

还有很多,现在我们就一纽约原料工厂为例啦,其他的都是差不多的。

来看看我们的抽象类Pizza(Pizza.java),第2-8行是披萨都持有的原料:

  1. 1 public abstract class Pizza {
  2. 2 String name;
  3. 3 Dough dough;
  4. 4 Sauce sauce;
  5. 5 Veggies veggies[];
  6. 6 Cheese cheese;
  7. 7 Pepperoni pepperoni;
  8. 8 Clams clam;
  9. 9
  10. 10 abstract void prepare();
  11. 11
  12. 12 void bake() {
  13. 13 System.out.println("Bake for 25 minutes at 350");
  14. 14 }
  15. 15
  16. 16 void cut() {
  17. 17 System.out.println("Cutting the pizza into diagonal slices");
  18. 18 }
  19. 19
  20. 20 void box() {
  21. 21 System.out.println("Place pizza in official PizzaStore box");
  22. 22 }
  23. 23
  24. 24 void setName(String name) {
  25. 25 this.name = name;
  26. 26 }
  27. 27
  28. 28 String getName() {
  29. 29 return name;
  30. 30 }
  31. 31
  32. 32 public String toString() {
  33. 33 StringBuffer result = new StringBuffer();
  34. 34 result.append("---- " + name + " ----\n");
  35. 35 if (dough != null) {
  36. 36 result.append(dough);
  37. 37 result.append("\n");
  38. 38 }
  39. 39 if (sauce != null) {
  40. 40 result.append(sauce);
  41. 41 result.append("\n");
  42. 42 }
  43. 43 if (cheese != null) {
  44. 44 result.append(cheese);
  45. 45 result.append("\n");
  46. 46 }
  47. 47 if (veggies != null) {
  48. 48 for (int i = 0; i < veggies.length; i++) {
  49. 49 result.append(veggies[i]);
  50. 50 if (i < veggies.length-1) {
  51. 51 result.append(", ");
  52. 52 }
  53. 53 }
  54. 54 result.append("\n");
  55. 55 }
  56. 56 if (clam != null) {
  57. 57 result.append(clam);
  58. 58 result.append("\n");
  59. 59 }
  60. 60 if (pepperoni != null) {
  61. 61 result.append(pepperoni);
  62. 62 result.append("\n");
  63. 63 }
  64. 64 return result.toString();
  65. 65 }
  66. 66 }

开始重做一个芝士披萨(CheesePizza.java),要做披萨,需要每个原料工厂提供原料。所以每个
披萨类都需要从构造器参数中得到一个工厂,并把这个工厂存储在一个实例变量中。在这里我们

实现了抽象类Pizza中的抽象方法prepare():

  1. 1 public class CheesePizza extends Pizza {
  2. 2 PizzaIngredientFactory ingredientFactory;
  3. 3
  4. 4 public CheesePizza(PizzaIngredientFactory ingredientFactory) {
  5. 5 this.ingredientFactory = ingredientFactory;
  6. 6 }
  7. 7
  8. 8 void prepare() {
  9. 9 System.out.println("Preparing " + name);
  10. 10 dough = ingredientFactory.createDough();
  11. 11 sauce = ingredientFactory.createSauce();
  12. 12 cheese = ingredientFactory.createCheese();
  13. 13 }
  14. 14 }

是时候回到披萨店了(纽约披萨店NYPizzaStore.java):

  1. 1 public class NYPizzaStore extends PizzaStore {
  2. 2
  3. 3 protected Pizza createPizza(String item) {
  4. 4 Pizza pizza = null;
  5. 5 PizzaIngredientFactory ingredientFactory = new NYPizzaIngredientFactory();
  6. 6
  7. 7 if (item.equals("cheese")) {
  8. 8
  9. 9 pizza = new CheesePizza(ingredientFactory);
  10. 10 pizza.setName("New York Style Cheese Pizza");
  11. 11
  12. 12 } else if (item.equals("veggie")) {
  13. 13
  14. 14 pizza = new VeggiePizza(ingredientFactory);
  15. 15 pizza.setName("New York Style Veggie Pizza");
  16. 16
  17. 17 } else if (item.equals("clam")) {
  18. 18
  19. 19 pizza = new ClamPizza(ingredientFactory);
  20. 20 pizza.setName("New York Style Clam Pizza");
  21. 21
  22. 22 } else if (item.equals("pepperoni")) {
  23. 23
  24. 24 pizza = new PepperoniPizza(ingredientFactory);
  25. 25 pizza.setName("New York Style Pepperoni Pizza");
  26. 26
  27. 27 }
  28. 28 return pizza;
  29. 29 }
  30. 30 }

 

现在添加一个测试类(Main.java):

  1. 1 public class Main {
  2. 2
  3. 3 public static void main(String[] args) {
  4. 4
  5. 5 Pizza pizza = nyStore.orderPizza("cheese");
  6. 6 System.out.println("Ethan ordered a " + pizza + "\n");
  7. 7
  8. 8 pizza = nyStore.orderPizza("clam");
  9. 9 System.out.println("Ethan ordered a " + pizza + "\n");
  10. 10
  11. 11 pizza = nyStore.orderPizza("pepperoni");
  12. 12 System.out.println("Ethan ordered a " + pizza + "\n");
  13. 13
  14. 14 pizza = nyStore.orderPizza("veggie");
  15. 15 System.out.println("Ethan ordered a " + pizza + "\n");
  16. 16 }
  17. 17 }

一切完成,现在让我们看一下这个项目的类图,有一点儿复杂,请静下心来看:

 

原文链接:http://www.cnblogs.com/Trojan00/p/11326688.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号