设计模式学习总结:(3)策略模式

策略模式(strategy):

属于行为模式

意图:

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

什么意思呢,我想的是,算法独立于客户,我们把一些算法具体实现封装起来,成为具体的类,而每一个算法独立为一种具体策略,把算法和环境(context)独立开来,这样有利于算法的扩展,很明显,这种模式很适合用于策略容易发生变化的业务。还是以具体的实例做基础吧。

假设这样的业务,游乐场,我们针对不同的项目,计算不同的开销,其实我不了解具体开销是不是以算法的形式,但是我们假设每一种开销有一种固定算法。假设一开始,我们支持过山车,碰碰车,海盗船,最简单的实现是这样:

enum GameType {
    Roller,   
    PoCar,
    PirateShip,
        //更改
};
class Economic:
{
private:
    GameType _g_Type;
public:
    double caculateOut()
   {
        switch(_g_Type)
        {
             case Roller:
                 //算法1
                 break;
             case  PoCar:
                  //算法2
                  break;
             case PirateShip:
                  //算法3
                  break;
         }
    }
}    

当然这样也是可以实现,但是这样不好,如果我们需要支持更多的项目,我们还要加多的枚举type,然后新增加一个case,比如自由落体项目,那还得修改代码。很明显违背了"开放封闭原则"。这样的例子是最好用策略模式的,首先,这里的确需要多种算法(策略),并且算法可能增加(变化)。运用策略模式,那么我们首先需要抽象一个策略基类。然后将算法从环境类(这里是Economic)里面分离出来,在策略基类中实现它们。

所以,改成这样是不是好一点:

定义抽象策略类。

class TypeStrategy
{
public:
    virtual double calculate()=0;
    ~virtual TypeStrategy;
}

 将已有业务算法实现:

class RollerStrategy:public TypeStrategy
{
public:
    double calculate()
    {
         //具体实现
    }
}
class PocarStrategy:public TypeStrategy
{
public:
    double calculate()
    {
         //具体实现
    }
}
class PirateShipStrategy:public TypeStrategy
{
public:
    double calculate()
    {
         //具体实现
    }
}

定义算法的执行环境类:

class Economic
{
private:
    TypeStrategy *_stgy;
public:
    Economic(StrategyFactory* factory)
    {
        _stgy  = factory->setup(); 
    }
    ~Economic()
    {
        delete _stgy;
    }

     double calculateOut()
     {
         return _stgy->calculate();
      }
}

如果有必要,还得定义一个context对象来保证算法和类之间的数据。

现在,我们假设需要增加一个项目,比如是鬼屋。

我们只需要定义我们的算法即可,做如下改动:

//扩展
class ShriedStrategy:public TypeStrategy
{
public:
    double calculate()
    {
     //具体实现
    }
}

而不需要对别的地方进行改动。保证了"开放封闭原则"。

书上给的策略模式结构图是这样的:

可以看到实现context和strategy的分离,然后对strategy进行抽象。

原文地址:https://www.cnblogs.com/wuweixin/p/5421740.html