C++设计模式课件4_策略模式.pdf

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

动机(Motivation)

在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂;而且有时候支持不使用的算法也是一个性能负担。

多余的if-else判断,增加代码体积, 降低命中率

如何在运行时根据需要透明地更改对象的算法?将算法与对象本身解耦,从而避免上述问题?

结构化软件设计流程

  1. enum TaxBase {
  2. CN_Tax,
  3. US_Tax,
  4. DE_Tax,
  5. FR_Tax //更改
  6. };
  7. class SalesOrder{
  8. TaxBase tax;
  9. public:
  10. double CalculateTax(){
  11. //...
  12. if (tax == CN_Tax){
  13. //CN***********
  14. }
  15. else if (tax == US_Tax){
  16. //US***********
  17. }
  18. else if (tax == DE_Tax){
  19. //DE***********
  20. }
  21. else if (tax == FR_Tax){ //更改
  22. //...
  23. }
  24. //....
  25. }
  26. };

面向对象软件设计流程

复用性: 编译单位的复用性, 二进制单位的复用, 不是源代码的复用性

  1. class TaxStrategy{
  2. public:
  3. virtual double Calculate(const Context& context)=0;
  4. virtual ~TaxStrategy(){}
  5. };
  6. class CNTax : public TaxStrategy{
  7. public:
  8. virtual double Calculate(const Context& context){
  9. //***********
  10. }
  11. };
  12. class USTax : public TaxStrategy{
  13. public:
  14. virtual double Calculate(const Context& context){
  15. //***********
  16. }
  17. };
  18. class DETax : public TaxStrategy{
  19. public:
  20. virtual double Calculate(const Context& context){
  21. //***********
  22. }
  23. };
  24. //扩展
  25. //*********************************
  26. class FRTax : public TaxStrategy{
  27. public:
  28. virtual double Calculate(const Context& context){
  29. //.........
  30. }
  31. };
  32. //复用
  33. class SalesOrder{
  34. private:
  35. TaxStrategy* strategy; // 多态指针; 若是对象则不支持多态了; 引用也可以
  36. public:
  37. SalesOrder(StrategyFactory* strategyFactory){
  38. // 工厂模式, 返回堆对象; 子类对象类型由工厂模式决定
  39. this->strategy = strategyFactory->NewStrategy();
  40. }
  41. ~SalesOrder(){
  42. delete this->strategy; // 删除堆对象
  43. }
  44. public double CalculateTax(){
  45. //...
  46. Context context();
  47. double val =
  48. strategy->Calculate(context); //多态调用
  49. //...
  50. }
  51. };

结构

image.png
稳定的部分: Context, Strategy
变化的部分: ConcreteStrategyA, ConcreteStrategyB, ConcreteStrategyC

要点总结

Strategy及其子类为组件提供了一系列可重用的算法,从而可以使得类型在运行时方便地根据需要在各个算法之间进行切换。

运行时:strategy->Calculate(context)

Strategy模式提供了用条件判断语句以外的另一种选择,消除条件判断语句,就是在解耦合。含有许多条件判断语句的代码通常都需要Strategy模式。

if-else

  • 结构化的分而治之思维
  • 对于if-else分支不扩展时,不适用Strategy模式

如果Strategy对象没有实例变量,那么各个上下文可以共享同一个Strategy对象,从而节省对象开销。

用Singleton