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

意图

定义算法族,将它们分别封装起来,让它们之间可以互相替换,此模式让算法的变化独立于算法的客户。

适用性

  1. 许多相关的类仅仅是行为有异。“策略”提供了一种用多个行为中的一个行为来配置一个类的方法。
  2. 需用使用一个算法的不同变体
  3. 算法使用客户不应该知道的数据。可使用策略模式以避免暴露复杂的、与算法相关的数据结构。
  4. 一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现。则可以将相关的条件分支迁入它们各自的strategy类中。

结构

优缺点

优点

  1. 封装了算法,是算法可以得到复用
  2. 通过将算法独立于客户,使系统更有弹性,使客户可以随时切换算法,易于理解与扩展
  3. 可以消除一些条件语句
  4. 可以提供相同行为的不同实现

缺点

  1. 客户在选择一个合适的strategy必须了解这些strategy之间有何不同,因此仅当这些不同行为是与客户相关的行为时,才需要使用strategy模式
  2. strategy和context之间存在通信开销
  3. 增加了类与对象的数目。有时你可以将strategy实现为可供context共享的无状态的对象来减少这一开销。任何其余的状态均由context维护,context在每次对strategy的请求中都将这个状态传递过去。享元(FlyWeight)模式更详细地描述了这一方法。

实现

考虑以下几个实现问题:
1.实际实现中Strategy必须要获取context中的数据。
一种方法是让context将所需数据作为参数传给strategy,这让strategy与context解耦,但在所需数据较多时接口参数将会很多,而且可能会发送一些strategy不需要的参数。

class Context
{
public:
    void Operation(){_theStrategy.DoAlgorithm(_data1, _data2);}
private:
    Strategy _theStrategy;
    int _data1;
    int _data2;
}

class Strategy
{
public:
    void DoAlgorithm(int data1, int data2)
    {
        ...
    }
}

另一种方法是将context自身作为参数传递给strategy,然后strategy显式地想context请求数据,但这样strategy与context更紧密地耦合在一起,而且需要为context定义更为精细的数据接口。

class Context
{
public:
    void Operation(){_theStrategy.DoAlgorithm(this);}
private:
    Strategy _theStrategy;
    int _data1;
    int _data2;
    float _data3;
    float _data4;
    double _data5;
}

class Strategy
{
public:
    void DoAlgorithm(const Context& context)
    {
        ...
    }
}

2.当一个context类可以在编译时确定其strategy并且在运行时不会改变其strategy时,则可以将context定义为一个以strategy类作为一个模板参数的模板类,如下:

template<class Strategy>
class Context
{
public:
    void Operation(){_theStrategy.DoAlgorithm();}
private:
    Strategy _theStrategy;
}

//两个不同的策略不需要从一个基类Strategy中继承
class StrategyA
{
public:
    void DoAlgorithm();
}

class StrategyB
{
public:
    void DoAlgorithm();
}

Context<StrategyA> contextA;
Context<StrategyB> contextB;

这样使用模板不再需要定义给Strategy定义的抽象类,通过将一个Strategy和它的Context静态绑定在一起,从而提高效率。

相关模式

享元(FlyWeight)模式:Strategy对象通常是很好的轻量级对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值