经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » 设计模式 » 查看文章
别只知道策略模式+简单工厂,试试更香的策略模式+抽象工厂!
来源:cnblogs  作者:一匹夫  时间:2021/3/24 9:09:40  对本文有异议

 

我的相关博文 

三种工厂模式详解

 

策略模式

在GOF的《设计模式:可复用面向对象软件的基础》一书中对策略模式是这样说的:

定义一系列的算法,把它们一个个封装起来,并且使它们可相互替换。该模式使得算法可独立于使用它的客户而变化。

 

策略模式为了适应不同的需求,只把变化点封装了,这个变化点就是实现不同需求的算法,例如加班工资,不同的加班情况,有不同的计算加班工资的方法。

我们不能在程序中将计算工资的算法进行硬编码,而能够自由变化。

这就是策略模式。

 

 

 

 

实验1 策略模式+简单工厂

代码

  1. #include <iostream>
  2. using namespace std;
  3. // Define the strategy type
  4. typedef enum StrategyType
  5. {
  6. StrategyA,
  7. StrategyB,
  8. StrategyC
  9. }STRATEGYTYPE;
  10. // The abstract strategy
  11. class Strategy
  12. {
  13. public:
  14. virtual void AlgorithmInterface(int x, int y) = 0;
  15. virtual ~Strategy() = 0;
  16. };
  17. Strategy::~Strategy()
  18. {}
  19. class ConcreteStrategyA : public Strategy
  20. {
  21. public:
  22. void AlgorithmInterface(int x, int y)
  23. {
  24. cout << "I am from ConcreteStrategyA: result=X+Y, = " << x+y << endl;
  25. }
  26. ~ConcreteStrategyA(){
  27. cout << "~ConcreteStrategyA()." << endl;
  28. }
  29. };
  30. class ConcreteStrategyB : public Strategy
  31. {
  32. public:
  33. void AlgorithmInterface(int x, int y)
  34. {
  35. cout << "I am from ConcreteStrategyB: result=X*Y, = " << x*y << endl;
  36. }
  37. ~ConcreteStrategyB(){
  38. cout << "~ConcreteStrategyB()." << endl;
  39. }
  40. };
  41. class ConcreteStrategyC : public Strategy
  42. {
  43. public:
  44. void AlgorithmInterface(int x, int y)
  45. {
  46. cout << "I am from ConcreteStrategyC: result=X-Y, = " << x-y << endl;
  47. }
  48. ~ConcreteStrategyC(){
  49. cout << "~ConcreteStrategyC()." << endl;
  50. }
  51. };
  52. // 用户类 : 使用算法的用户
  53. class Context
  54. {
  55. public:
  56. // 该构造函数内使用简单工厂模式
  57. Context(STRATEGYTYPE strategyType)
  58. {
  59. switch (strategyType)
  60. {
  61. case StrategyA:
  62. pStrategy = new ConcreteStrategyA;
  63. break;
  64. case StrategyB:
  65. pStrategy = new ConcreteStrategyB;
  66. break;
  67. case StrategyC:
  68. pStrategy = new ConcreteStrategyC;
  69. break;
  70. default:
  71. break;
  72. }
  73. }
  74. ~Context()
  75. {
  76. if (pStrategy)
  77. delete pStrategy;
  78. }
  79. void ContextInterface(int x, int y) // 定义一个接口来让Stategy访问用户的数据
  80. {
  81. if (pStrategy)
  82. pStrategy->AlgorithmInterface(x, y);
  83. }
  84. private:
  85. Strategy *pStrategy; // 维护一个对Stategy对象的引用或指针
  86. int a; // 私有数据,这是用户数据,该用户是独立于算法的用户,用户不需要了解算法内部的数据结构
  87. int b;
  88. };
  89. int main()
  90. {
  91. Context *pContext = new Context(StrategyA);
  92. pContext->ContextInterface(100, 6);
  93. if (pContext)
  94. delete pContext;
  95. }

上述的例子是策略模式,我们还能看到一点简单工厂模式的影子。

百度到的绝大多数都是这种例子了。 这个代码完美吗?看下GoF的要领:

如果我们需要新增新的算法,我们需要修改Context类的构造函数,在里面新增新的算法,这显然不符合GoF采用扩展、子类化的精要。

所以引出了我下面的策略模式+抽象工厂的解决方案。

 

 

实验2 策略模式+抽象工厂

代码

  1. #include <iostream>
  2. using namespace std;
  3. // The abstract strategy
  4. class Strategy
  5. {
  6. public:
  7. virtual void AlgorithmInterface(int x, int y) = 0;
  8. virtual ~Strategy() = 0;
  9. };
  10. Strategy::~Strategy()
  11. {}
  12. class ConcreteStrategyA : public Strategy
  13. {
  14. public:
  15. void AlgorithmInterface(int x, int y)
  16. {
  17. cout << "I am from ConcreteStrategyA: result=X+Y, = " << x+y << endl;
  18. }
  19. ~ConcreteStrategyA(){
  20. cout << "~ConcreteStrategyA().析够" << endl;
  21. }
  22. };
  23. class ConcreteStrategyB : public Strategy
  24. {
  25. public:
  26. void AlgorithmInterface(int x, int y)
  27. {
  28. cout << "I am from ConcreteStrategyB: result=X*Y, = " << x*y << endl;
  29. }
  30. ~ConcreteStrategyB(){
  31. cout << "~ConcreteStrategyB().析够" << endl;
  32. }
  33. };
  34. class ConcreteStrategyC : public Strategy
  35. {
  36. public:
  37. void AlgorithmInterface(int x, int y)
  38. {
  39. cout << "I am from ConcreteStrategyC: result=X-Y, = " << x-y << endl;
  40. }
  41. ~ConcreteStrategyC(){
  42. cout << "~ConcreteStrategyC().析够" << endl;
  43. }
  44. };
  45. // 用户类 : 使用算法的用户
  46. class Context
  47. {
  48. public:
  49. Context(Strategy* paraStrategy)
  50. {
  51. pStrategy = paraStrategy;
  52. }
  53. ~Context()
  54. {
  55. // 这里不需要析够pStrategy, pStrategy对应对象的析够会在delete pAbstractStrategyFactory时进行。
  56. // 即,销毁具体某个策略工厂对象时会负责析够具体的策略对象。所以这里就不需要了。
  57. }
  58. void ContextInterface(int x, int y) // 定义一个接口来让Stategy访问用户的数据
  59. {
  60. if (pStrategy)
  61. pStrategy->AlgorithmInterface(x, y);
  62. }
  63. private:
  64. Strategy *pStrategy; // 维护一个对Stategy对象的引用或指针
  65. int a; // 私有数据,这是用户数据,该用户是独立于算法的用户,用户不需要了解算法内部的数据结构
  66. int b;
  67. };
  68. // 点评该类: 一条产品线下的产品,通常存在共性,
  69. // 也就是说,维护一个对产品的抽象类通常是需要的,而不是必须的。
  70. class AbstractStrategyFactory // 抽象工厂这里可以实现多个纯虚方法
  71. {
  72. public:
  73. virtual Strategy* createStrategy(string Strategy)=0;
  74. virtual ~AbstractStrategyFactory(){}
  75. };
  76. class StrategyA_Factory:public AbstractStrategyFactory
  77. {
  78. Strategy *pStrategy;
  79. public:
  80. StrategyA_Factory():pStrategy(NULL)
  81. {}
  82. Strategy* createStrategy(string Strategy)
  83. {
  84. if(Strategy == "StrategyA"){
  85. pStrategy = new ConcreteStrategyA();
  86. return pStrategy;
  87. }
  88. return NULL;
  89. }
  90. ~StrategyA_Factory()
  91. {
  92. cout << "~StrategyA_Factory(). 析够" << endl;
  93. if(pStrategy)
  94. delete pStrategy;
  95. }
  96. };
  97. class StrategyB_Factory:public AbstractStrategyFactory
  98. {
  99. Strategy *pStrategy;
  100. public:
  101. StrategyB_Factory():pStrategy(NULL)
  102. {}
  103. Strategy* createStrategy(string Strategy)
  104. {
  105. if(Strategy == "StrategyB"){
  106. pStrategy = new ConcreteStrategyB();
  107. return pStrategy;
  108. }
  109. return NULL;
  110. }
  111. ~StrategyB_Factory()
  112. {
  113. if(pStrategy)
  114. delete pStrategy;
  115. }
  116. };
  117. class StrategyC_Factory:public AbstractStrategyFactory
  118. {
  119. Strategy *pStrategy;
  120. public:
  121. StrategyC_Factory():pStrategy(NULL)
  122. {}
  123. Strategy* createStrategy(string Strategy)
  124. {
  125. if(Strategy == "StrategyC"){
  126. pStrategy = new ConcreteStrategyC();
  127. return pStrategy;
  128. }
  129. return NULL;
  130. }
  131. ~StrategyC_Factory()
  132. {
  133. if(pStrategy)
  134. delete pStrategy;
  135. }
  136. };
  137. int main(int argc, char *argv[])
  138. {
  139. AbstractStrategyFactory* pAbstractStrategyFactory; // 创建抽象工厂指针
  140. pAbstractStrategyFactory = new StrategyA_Factory(); // 创建策略A的工厂
  141. Strategy* pStrategy = pAbstractStrategyFactory->createStrategy("StrategyA"); //使用策略A工厂来生产出策略A
  142. if(pStrategy == NULL)
  143. {
  144. cout << "pStrategy is NULL" << endl;
  145. }
  146. else
  147. {
  148. // 供用户来使用策略A : 用户使用策略A 和 策略A的实现,是松耦合的。
  149. Context *pContext = new Context(pStrategy);
  150. pContext->ContextInterface(100, 6);
  151. delete pAbstractStrategyFactory;
  152. if (pContext)
  153. delete pContext;
  154. }
  155. return 0;
  156. }

编译运行:

 

此时,如果要新增算法,那我觉得可以采用扩展、子类化的解决方案了,而不用像本博文上一个例子那样,去修改已有的代码了。

说大白话,如果要新增算法,现在只需要在已有代码基础上去新增新算法的相关代码,而不是去修改已经写好的一些函数的内部实现。

当然,这样的设计会导致代码量变大,所以一切都需要权衡,适合自己的就是最好的。

 

 

 

.

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