第五课 工厂方法模式
这个模式用法通过例子很容易学会,但是我一直没能体会到他存在的意义,他能提供的好处。所以在群里讨论了下,也没有搞明白。最终,无意中在Java编程思想中看到了一个工厂方法的应用,突然大彻大悟(呵呵),谁说工厂方法只能零散着调用,可以结合别的模式一起使用吗。呵呵,下面进入正题。
首先回想一下简单工厂的优缺点。
优点:
对产品对象能够很好的实现开闭原则。能够将复杂的获取哪个对象逻辑判断封装到具体的工厂类中,具体判断不对客户端(调用程序)开发,达到了逻辑封装的效果。
缺点:
如果新增新的产品,除了要实现新的产品外,还必须要修改工厂方法。
上一讲我说了,正由于这个缺点的存在,诞生了工厂方法模式。
工厂方法的思想是,对工厂类进行进一步的抽象,将他的抽象和实现也进行分离。从而实现开闭原则。这样根据依赖倒转原则,我们将处理的重点放在抽象上,不去依赖具体的实现。这里思路与产品一样。将工厂方法的核心抽象出一个工厂方法的基类(或接口)。由具体的工厂实现类来依照我们的处理思路去实现工厂方法。下面看实例代码。
(Java与模式的例子很空洞,这里引用大话设计模式的例子)
C#:
1. using System;
2. using System.Collections.Generic;
3. using System.Text;
4.
5. namespace 工厂方法_计算器
6. {
7.
8. /// <summary>
9. /// 运算类
10. /// </summary>
11. class Operation
12. {
13. private double _numberA = 0;
14. private double _numberB = 0;
15.
16. public double NumberA
17. {
18. get { return _numberA; }
19. set { _numberA = value; }
20. }
21.
22. public double NumberB
23. {
24. get { return _numberB; }
25. set { _numberB = value; }
26. }
27.
28. /// <summary>
29. /// 得到运算结果
30. /// </summary>
31. /// <returns></returns>
32. public virtual double GetResult()
33. {
34. double result = 0;
35. return result;
36. }
37. }
38.
39. /// <summary>
40. /// 加法类
41. /// </summary>
42. class OperationAdd : Operation
43. {
44. public override double GetResult()
45. {
46. double result = 0;
47. result = NumberA + NumberB;
48. return result;
49. }
50. }
51.
52. /// <summary>
53. /// 减法类
54. /// </summary>
55. class OperationSub : Operation
56. {
57. public override double GetResult()
58. {
59. double result = 0;
60. result = NumberA - NumberB;
61. return result;
62. }
63. }
64. /// <summary>
65. /// 乘法类
66. /// </summary>
67. class OperationMul : Operation
68. {
69. public override double GetResult()
70. {
71. double result = 0;
72. result = NumberA * NumberB;
73. return result;
74. }
75. }
76. /// <summary>
77. /// 除法类
78. /// </summary>
79. class OperationDiv : Operation
80. {
81. public override double GetResult()
82. {
83. double result = 0;
84. if (NumberB == 0)
85. throw new Exception("除数不能为0。");
86. result = NumberA / NumberB;
87. return result;
88. }
89. }
90.
91. /// <summary>
92. /// 工厂方法
93. /// </summary>
94. interface IFactory
95. {
96. Operation CreateOperation();
97. }
98.
99. /// <summary>
100. /// 专门负责生产“+”的工厂
101. /// </summary>
102. class AddFactory : IFactory
103. {
104. public Operation CreateOperation()
105. {
106. return new OperationAdd();
107. }
108. }
109.
110. /// <summary>
111. /// 专门负责生产“-”的工厂
112. /// </summary>
113. class SubFactory : IFactory
114. {
115. public Operation CreateOperation()
116. {
117. return new OperationSub();
118. }
119. }
120.
121. /// <summary>
122. /// 专门负责生产“*”的工厂
123. /// </summary>
124. class MulFactory : IFactory
125. {
126. public Operation CreateOperation()
127. {
128. return new OperationMul();
129. }
130. }
131.
132. /// <summary>
133. /// 专门负责生产“/”的工厂
134. /// </summary>
135. class DivFactory : IFactory
136. {
137. public Operation CreateOperation()
138. {
139. return new OperationDiv();
140. }
141. }
142.
143. class DoOperation
144. {
145. public static double DoComboOperation(IFactory fac,double a,double b)
146. {
147. Operation op = fac.CreateOperation();
148. op.NumberA = a;
149. op.NumberB = b;
150. return op.GetResult();
151. }
152. }
153. }
154.
里面除去DoOperation是我加的外,全部原版代码。可以说是工厂方法模式的标准实现方法了。下面咱们分析一下。首先在产品这部分,处理思路和简单工厂是一样的,这里不再提了。工厂这里注意一下。他也采用了类似产品的做法,抽象了一个接口IFactory 然后在观察那几个具体的实现的工厂类, AddFactory 等,这是就会发现,每一个产品对象都有自己的工厂。其实我原来就在这里有疑问,这样确实避免了简单工厂的缺点,新增产品的时候只需要新增生产这个产品的工厂,不需要修改工厂接口。但是感觉在使用的时候没有什么方便。所以一直在怀疑他的存在价值。现在我多少明白了一点。看我新加的DoOperation 类。里面有DoComboOperation方法,参数是IFactory和两个运算数。现在来看了。我如果要执行加法,我传入一个加法工厂和两个值,即可,我如果执行减法,我传入减法工厂和两个值。这样直接将产品给完全隔离了,对外只有工厂接口。能感觉到点意思了吧。想象下,如果我这里又复杂的处理逻辑呢,并且加减乘除都能够操作。(Java思想里面例子是下棋,不同的棋走不同的步数)这个方法是模板模式。模板模式和工厂方法结合的时候,就能体现工厂方法的意义了。并且工厂方法通过DoOperation 这种方式甚至可以完全隔离产品。
可能你还很晕哦,但是先记住这种用法,到实践中去体会吧。
工厂方法就到这里,下次我们来看抽象工厂模式。
作者:王文斌
转载请注明出处哦