• Strategy 策略模式


    意图

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

    动机

    策略模式为了适应不同的需求,只把变化点封装了,这个变化点就是实现不同需求的算法,但是,用户需要知道各种算法的具体情况。就像上面的加班工资,不同的加班情况,有不同的算法。我们不能在程序中将计算工资的算法进行硬编码,而是能自由的变化的。这就是策略模式。

    刚刚加班回来;哎,公司规定平时加班只有10块钱的餐补;星期六和星期天加班,只给串休假;在国家规定的节假日按照3倍工资发放。那么对于这么多的计算加班费的方法,公司的OA系统是如何进行做的呢?各种计算加班费的情况就可以认为是策略模式

    适用性

    • 许多相关的类仅仅是行为有异。 “策略”提供了一种用多个行为中的一个行为来配置一个类的方法。
    • 需要使用一个算法的不同变体。例如,你可能会定义一些反映不同的空间 /时间权衡的算法。当这些变体实现为一个算法的类层次时,可以使用策略模式
    • 算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。
    • 一个类定义了多种行为 , 并且这些行为在这个类的操作中以多个条件语句的形式出现。将相关的条件分支移入它们各自的Strategy类中以代替这些条件语句。

    结构

    参与者

    Strategy:定义所有支持的算法的公共接口。Context使用这个接口来调用某ConcreteStrategy定义的算法;
    ConcreteStrategy:实现Strategy接口的具体算法;
    Context:使用一个ConcreteStrategy对象来配置;维护一个对Stategy对象的引用,同时,可以定义一个接口来让Stategy访问它的数据。

    效果

    相关算法系列Strategy类层次为Context定义了一系列的可供重用的算法或行为。继承有助于析取出这些算法中的公共功能。

    实现

    纯策略模式,实际上就是父类为纯虚函数,子类根据需求实现各种方法

     1 #include <iostream>
     2 using namespace std;
     3 
     4 // The abstract strategy
     5 class Strategy
     6 {
     7 public:
     8      virtual void AlgorithmInterface() = 0;
     9 };
    10 
    11 class ConcreteStrategyA : public Strategy
    12 {
    13 public:
    14      void AlgorithmInterface()
    15      {
    16           cout<<"I am from ConcreteStrategyA."<<endl;
    17      }
    18 };
    19 
    20 class ConcreteStrategyB : public Strategy
    21 {
    22 public:
    23      void AlgorithmInterface()
    24      {
    25           cout<<"I am from ConcreteStrategyB."<<endl;
    26      }
    27 };
    28 
    29 class ConcreteStrategyC : public Strategy
    30 {
    31 public:
    32      void AlgorithmInterface()
    33      {
    34           cout<<"I am from ConcreteStrategyC."<<endl;
    35      }
    36 };
    37 
    38 class Context
    39 {
    40 public:
    41      Context(Strategy *pStrategyArg) : pStrategy(pStrategyArg)
    42      {
    43      }
    44      void ContextInterface()
    45      {
    46           pStrategy->AlgorithmInterface();
    47      }
    48 private:
    49      Strategy *pStrategy;
    50 };
    51 
    52 int main()
    53 {
    54      // Create the Strategy
    55      Strategy *pStrategyA = new ConcreteStrategyA;
    56      Strategy *pStrategyB = new ConcreteStrategyB;
    57      Strategy *pStrategyC = new ConcreteStrategyC;
    58      Context *pContextA = new Context(pStrategyA);
    59      Context *pContextB = new Context(pStrategyB);
    60      Context *pContextC = new Context(pStrategyC);
    61      pContextA->ContextInterface();
    62      pContextB->ContextInterface();
    63      pContextC->ContextInterface();
    64 
    65      if (pStrategyA) delete pStrategyA;
    66      if (pStrategyB) delete pStrategyB;
    67      if (pStrategyC) delete pStrategyC;
    68 
    69      if (pContextA) delete pContextA;
    70      if (pContextB) delete pContextB;
    71      if (pContextC) delete pContextC;
    72 }

    在实际操作的过程中,我们会发现,在main函数中,也就是在客户端使用策略模式时,会创建非常多的Strategy,而这样就莫名的增加了客户端的压力,让客户端的复杂度陡然增加了。那么,我们就可以借鉴简单工厂模式,使策略模式和简单工厂模式相结合,从而减轻客户端的压力,代码实现如下:

      1 #include <iostream>
      2 using namespace std;
      3 
      4 // Define the strategy type
      5 typedef enum StrategyType
      6 {
      7     StrategyA,
      8     StrategyB,
      9     StrategyC
     10 }STRATEGYTYPE;
     11 
     12 // The abstract strategy
     13 class Strategy
     14 {
     15 public:
     16     virtual void AlgorithmInterface() = 0;
     17     virtual ~Strategy() = 0; // 谢谢hellowei提出的bug,具体可以参见评论
     18 };
     19 
     20 Strategy::~Strategy()
     21 {}
     22 
     23 class ConcreteStrategyA : public Strategy
     24 {
     25 public:
     26     void AlgorithmInterface()
     27     {
     28         cout << "I am from ConcreteStrategyA." << endl;
     29     }
     30 
     31     ~ConcreteStrategyA(){}
     32 };
     33 
     34 class ConcreteStrategyB : public Strategy
     35 {
     36 public:
     37     void AlgorithmInterface()
     38     {
     39         cout << "I am from ConcreteStrategyB." << endl;
     40     }
     41 
     42     ~ConcreteStrategyB(){}
     43 };
     44 
     45 class ConcreteStrategyC : public Strategy
     46 {
     47 public:
     48     void AlgorithmInterface()
     49     {
     50         cout << "I am from ConcreteStrategyC." << endl;
     51     }
     52 
     53     ~ConcreteStrategyC(){}
     54 };
     55 
     56 class Context
     57 {
     58 public:
     59     Context(STRATEGYTYPE strategyType)
     60     {
     61         switch (strategyType)
     62         {
     63         case StrategyA:
     64             pStrategy = new ConcreteStrategyA;
     65             break;
     66 
     67         case StrategyB:
     68             pStrategy = new ConcreteStrategyB;
     69             break;
     70 
     71         case StrategyC:
     72             pStrategy = new ConcreteStrategyC;
     73             break;
     74 
     75         default:
     76             break;
     77         }
     78     }
     79 
     80     ~Context()
     81     {
     82         if (pStrategy) delete pStrategy;
     83     }
     84 
     85     void ContextInterface()
     86     {
     87         if (pStrategy)
     88             pStrategy->AlgorithmInterface();
     89     }
     90 
     91 private:
     92     Strategy *pStrategy;
     93 };
     94 
     95 int main()
     96 {
     97     Context *pContext = new Context(StrategyA);
     98     pContext->ContextInterface();
     99 
    100     if (pContext) delete pContext;
    101 }
  • 相关阅读:
    Python基础入门教程
    【前端学习笔记】2015-09-11~~~~ js中ajax请求返回案例
    【前端学习笔记】2015-09-10~~~~ css层叠样式表~~格式
    【前端学习笔记】2015-09-09~~~~nodejs中的require()和module.exports
    【前端学习笔记】2015-09-08~~~~ 关于切图的简单方法
    【前端学习笔记】2015-09-06 ~~~~ setAttribute()、slice()
    【前端学习笔记】2015-09-02 附~~~~~ajax简单请求和获得响应结果
    【前端学习笔记】2015-09-02~~~~ 关于filter()匹配的使用
    【前端学习笔记】2015-09-01 附二 关于jq选择器的简单运用
    【前端学习笔记】2015-09-01 附 split()方法、readyState
  • 原文地址:https://www.cnblogs.com/raichen/p/5673575.html
Copyright © 2020-2023  润新知