经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
设计模式-创建型-工厂模式
来源:cnblogs  作者:酷学大叔  时间:2019/9/16 9:17:49  对本文有异议

工厂设计模式:

  顾名思义,该模式是用来生产对象的。在面向对象的设计模式中,万物皆对象,若使用new来创建对象,就会对该对象产生强耦合,加入我们需要更换该对象,那么使用该对象的对象都需要进行修改,这显然违背了开闭原则(OCP)。如果我们使用工厂来产生对象,我们只需要与这个工厂打交道就可以了,无需关心具体的对象,达到解耦的目的。

  接下来我们从实际的案例出发,从无工厂到有工厂的区别。

  去披萨店订购披萨,首先披萨的种类很多(CheesePizza、GreekPizza、DurianPizza{等),披萨的制作流程有prepare、bake、cut、box。

传统模式:

   

  1. 1 internal class Program
  2. 2 {
  3. 3 private static void Main(string[] args)
  4. 4 {
  5. 5 new OrderPizza();
  6. 6 }
  7. 7 }
  8. 8
  9. 9 internal class OrderPizza
  10. 10 {
  11. 11 public OrderPizza()
  12. 12 {
  13. 13 Pizza pizza = null;
  14. 14 string orderType = "";
  15. 15 do
  16. 16 {
  17. 17 orderType = Console.ReadLine();
  18. 18 if (orderType == "cheese")
  19. 19 {
  20. 20 pizza = new CheesePizza();
  21. 21 pizza.setName("芝士披萨");
  22. 22 }
  23. 23 else if (orderType == "greek")
  24. 24 {
  25. 25 pizza = new GreekPizza();
  26. 26 pizza.setName("希腊披萨");
  27. 27 }
  28. 28 else
  29. 29 {
  30. 30 Console.WriteLine("订购失败");
  31. 31 break;
  32. 32 }
  33. 33 //开始制作
  34. 34 pizza.prepare();
  35. 35 pizza.bake();
  36. 36 pizza.cut();
  37. 37 pizza.box();
  38. 38 } while (true);
  39. 39 }
  40. 40 }
  41. 41
  42. 42 internal abstract class Pizza
  43. 43 {
  44. 44 private string name;
  45. 45
  46. 46 public abstract void prepare();
  47. 47
  48. 48 public void bake()
  49. 49 {
  50. 50 Console.WriteLine($"{this.name} 烘培");
  51. 51 }
  52. 52
  53. 53 public void cut()
  54. 54 {
  55. 55 Console.WriteLine($"{this.name} 修剪");
  56. 56 }
  57. 57
  58. 58 public void box()
  59. 59 {
  60. 60 Console.WriteLine($"{this.name} 打包");
  61. 61 }
  62. 62
  63. 63 public void setName(string name)
  64. 64 {
  65. 65 this.name = name;
  66. 66 }
  67. 67 }
  68. 68
  69. 69 internal class CheesePizza : Pizza
  70. 70 {
  71. 71 public override void prepare()
  72. 72 {
  73. 73 Console.WriteLine("芝士披萨准备中");
  74. 74 }
  75. 75 }
  76. 76
  77. 77 internal class GreekPizza : Pizza
  78. 78 {
  79. 79 public override void prepare()
  80. 80 {
  81. 81 Console.WriteLine("希腊披萨准备中");
  82. 82 }
  83. 83 }
view code

  传统模式的优缺点:

    1、比较好理解,易于操作

    2、违反OCP原则,即对扩展开放,对修改关闭。

    3、这里只订购了两种pizza,若现在又新增了品种DurianPizza,这个时候就需要添加该类以及修改OrderPizza中的代码。从上图中可以看出,OrderPizza依赖抽象类及具体实现类的,那怎样才能切断OrderPizza与类之间的依赖关系呢。于是我们想到,可以定义一个工厂,订购者不需要知道具体pizza的制作流程,只要直到我需要订购什么类型的pizza就行了。

 

简单工厂模式:

   

  1. 1 internal class Program
  2. 2 {
  3. 3 private static void Main(string[] args)
  4. 4 {
  5. 5 new OrderPizza();
  6. 6 }
  7. 7 }
  8. 8
  9. 9 internal class OrderPizza
  10. 10 {
  11. 11 public OrderPizza()
  12. 12 {
  13. 13 Pizza pizza = null;
  14. 14 string orderType = "";
  15. 15 do
  16. 16 {
  17. 17 Console.Write("请输入订购类型:");
  18. 18 orderType = Console.ReadLine();
  19. 19 pizza = SimpleFactory.createPizza(orderType);
  20. 20 if (pizza == null)
  21. 21 {
  22. 22 Console.WriteLine("订购失败");
  23. 23 break;
  24. 24 }
  25. 25 //开始制作
  26. 26 pizza.prepare();
  27. 27 pizza.bake();
  28. 28 pizza.cut();
  29. 29 pizza.box();
  30. 30 } while (true);
  31. 31 }
  32. 32 }
  33. 33
  34. 34 internal static class SimpleFactory
  35. 35 {
  36. 36 public static Pizza createPizza(string orderType)
  37. 37 {
  38. 38 Pizza pizza = null;
  39. 39 do
  40. 40 {
  41. 41 if (orderType == "cheese")
  42. 42 {
  43. 43 pizza = new CheesePizza();
  44. 44 pizza.setName("芝士披萨");
  45. 45 }
  46. 46 else if (orderType == "greek")
  47. 47 {
  48. 48 pizza = new GreekPizza();
  49. 49 pizza.setName("希腊披萨");
  50. 50 }
  51. 51 else if (orderType == "durian")
  52. 52 {
  53. 53 pizza = new DurianPizza();
  54. 54 pizza.setName("榴莲披萨");
  55. 55 }
  56. 56 return pizza;
  57. 57 } while (true);
  58. 58 }
  59. 59 }
  60. 60
  61. 61 internal abstract class Pizza
  62. 62 {
  63. 63 private string name;
  64. 64
  65. 65 public abstract void prepare();
  66. 66
  67. 67 public void bake()
  68. 68 {
  69. 69 Console.WriteLine($"{this.name} 烘培");
  70. 70 }
  71. 71
  72. 72 public void cut()
  73. 73 {
  74. 74 Console.WriteLine($"{this.name} 修剪");
  75. 75 }
  76. 76
  77. 77 public void box()
  78. 78 {
  79. 79 Console.WriteLine($"{this.name} 打包");
  80. 80 }
  81. 81
  82. 82 public void setName(string name)
  83. 83 {
  84. 84 this.name = name;
  85. 85 }
  86. 86 }
  87. 87
  88. 88 internal class CheesePizza : Pizza
  89. 89 {
  90. 90 public override void prepare()
  91. 91 {
  92. 92 Console.WriteLine("芝士披萨准备中");
  93. 93 }
  94. 94 }
  95. 95
  96. 96 internal class GreekPizza : Pizza
  97. 97 {
  98. 98 public override void prepare()
  99. 99 {
  100. 100 Console.WriteLine("希腊披萨准备中");
  101. 101 }
  102. 102 }
  103. 103
  104. 104 internal class DurianPizza : Pizza
  105. 105 {
  106. 106 public override void prepare()
  107. 107 {
  108. 108 Console.WriteLine("榴莲披萨准备中");
  109. 109 }
  110. 110 }
view code

  简单工厂模式优缺点:

    1、由代码可以看出,虽然简单工厂模式一定程度上减少了因需求变更而导致的代码更改,但是实际仍违背了OCP原则。

    2、所以简单工厂模式只适合产品对象相对较少,且产品固定的需求,对产品变化无常的需求来说显然不适合。

 

工厂方法设计模式:

  披萨项目需求变更,客户点披萨时可以点不同口味的披萨。 

   

  1. 1 internal class Program
  2. 2 {
  3. 3 private static void Main(string[] args)
  4. 4 {
  5. 5 new BJOrderPizza();
  6. 6 }
  7. 7 }
  8. 8
  9. 9 internal abstract class OrderPizza
  10. 10 {
  11. 11 public OrderPizza()
  12. 12 {
  13. 13 Pizza pizza = null;
  14. 14 string orderType = "";
  15. 15 do
  16. 16 {
  17. 17 Console.Write("请输入订购类型:");
  18. 18 orderType = Console.ReadLine();
  19. 19 pizza = createPizza(orderType);
  20. 20 if (pizza == null)
  21. 21 {
  22. 22 Console.WriteLine("订购失败");
  23. 23 break;
  24. 24 }
  25. 25 //开始制作
  26. 26 pizza.prepare();
  27. 27 pizza.bake();
  28. 28 pizza.cut();
  29. 29 pizza.box();
  30. 30 } while (true);
  31. 31 }
  32. 32
  33. 33 public abstract Pizza createPizza(string orderType);
  34. 34 }
  35. 35
  36. 36 internal class BJOrderPizza : OrderPizza
  37. 37 {
  38. 38 public override Pizza createPizza(string orderType)
  39. 39 {
  40. 40 Pizza pizza = null;
  41. 41 if (orderType == "cheese")
  42. 42 {
  43. 43 pizza = new BJCheesePizza();
  44. 44 }
  45. 45 else if (orderType == "greek")
  46. 46 {
  47. 47 pizza = new BJGreekPizza();
  48. 48 }
  49. 49 return pizza;
  50. 50 }
  51. 51 }
  52. 52
  53. 53 internal class LDOrderPizza : OrderPizza
  54. 54 {
  55. 55 public override Pizza createPizza(string orderType)
  56. 56 {
  57. 57 Pizza pizza = null;
  58. 58 if (orderType == "cheese")
  59. 59 {
  60. 60 pizza = new LDCheesePizza();
  61. 61 }
  62. 62 else if (orderType == "greek")
  63. 63 {
  64. 64 pizza = new LDGreekPizza();
  65. 65 }
  66. 66 return pizza;
  67. 67 }
  68. 68 }
  69. 69
  70. 70 internal abstract class Pizza
  71. 71 {
  72. 72 private string name;
  73. 73
  74. 74 public abstract void prepare();
  75. 75
  76. 76 public void bake()
  77. 77 {
  78. 78 Console.WriteLine($"{this.name} 烘培");
  79. 79 }
  80. 80
  81. 81 public void cut()
  82. 82 {
  83. 83 Console.WriteLine($"{this.name} 修剪");
  84. 84 }
  85. 85
  86. 86 public void box()
  87. 87 {
  88. 88 Console.WriteLine($"{this.name} 打包");
  89. 89 }
  90. 90
  91. 91 public void setName(string name)
  92. 92 {
  93. 93 this.name = name;
  94. 94 }
  95. 95 }
  96. 96
  97. 97 internal class BJCheesePizza : Pizza
  98. 98 {
  99. 99 public override void prepare()
  100. 100 {
  101. 101 Console.WriteLine("北京的芝士披萨准备中");
  102. 102 }
  103. 103 }
  104. 104
  105. 105 internal class BJGreekPizza : Pizza
  106. 106 {
  107. 107 public override void prepare()
  108. 108 {
  109. 109 Console.WriteLine("北京的希腊披萨准备中");
  110. 110 }
  111. 111 }
  112. 112
  113. 113 internal class LDCheesePizza : Pizza
  114. 114 {
  115. 115 public override void prepare()
  116. 116 {
  117. 117 Console.WriteLine("伦敦的芝士披萨准备中");
  118. 118 }
  119. 119 }
  120. 120
  121. 121 internal class LDGreekPizza : Pizza
  122. 122 {
  123. 123 public override void prepare()
  124. 124 {
  125. 125 Console.WriteLine("伦敦的希腊披萨准备中");
  126. 126 }
  127. 127 }
view code

  工厂方法模式的优缺点:

    1、让父类的实现延迟到子类中去,减少判断。

    2、换汤不换药,和简单工厂模式类似,一般适用于产品对象相对较少,且产品固定的需求。

    3、工厂方法一定程度上减轻了工厂的职责,将职责细化,避免工厂类无法正常运行而导致程序崩溃。

参考:https://www.jianshu.com/p/38493eb4ffbd 

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