策略模式(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进行抽象。