策略模式 Strategy:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。本模式使算法可以独立于使用它的客户而变化。
先来看一个简单的伪码示例:
//抽象策略
class Compositor
{
public:
virtual int Compose() = NULL;
};
//上下文
class Composition
{
public:
Composition(Compositor* aCom);
void Repair()
{
iCompositor->Compose();
}
/*
* ...省略...*/
private:
Compositor* iCompositor;
};
//具体策略
class SimpleCompositor : public Compositor
{
public:
int Compose(){ /*......*/}
};
class ComplexCompositor : public Compositor
{
public:
int Compose(){ /*......*/}
};
//使用
Composition* com1 = new Composition(new SimpleCompositor);
Composition* com2 = new Composition(new ComplexCompositor);
com1->Repair();
com2->Repair();
以上就是一个策略模式的简单示例,看完后我思考为什么用这样的方式处理,这是个很简单的问题,为什么不在Compostion中硬编码Compose的不同实现?只需要根据不同的情况做一个switch判断就可以。
GOF设计模式中对这个问题进行了解释:
1. 把不同的算法集中到Composition中会使代码变的复杂难以维护,新增或改变现有算法将变得困难
2. 硬编码不符合开闭原则,如需要新增算法必须修改Composition代码。
模式组成:
Strategy:抽象策略,定义所有支持的算法的公共接口。
ConcreteStrategy:具体策略,以某种算法实现Strategy中的抽象接口
Context:上下文,用一个ConcrectStrategy对象来配置,维护一个对Strategy对象的引用,可以定义一个接口来让Strategy访问它的数据。
其结构如图:
一个类定义了多种行为,并且这些行为在这个类的操作中以多个条件语句的形式出现时。就可以用策略模式,将相关的条件分支移入各自的Strategy类中以代替这些条件语句。
效果,优点缺点
替代继承:可以用继承的方式解决不同算法的问题,每一种算法生成一个专门的Context子类,从而产生不同行为。但是这会将行为硬编码到Context中,不能动态改变算法,最后你得到一堆相关的类,而它们之间的唯一差别是使用的算法或行为。(注意:出现这种情况的代码可以修改为策略模式)
清除一些条件语句:用策略模式的处理方式替代条件分支。
增加了对象的数目:
实现
将Strategy做为模板参数:可以利用C++的模板机制用一个Strategy配置一个类,但是需要编译时刻确定Strategy的类型。这样提能够高效率。
使Strategy对象成为可选:只需要Context访问Strategy时判断它是否存在,然后选择使用缺省行为。
相关模式:
FlyWeight:把Strategy对象做成轻量级对象。