1.策略模式的动机
软件构建过程中,某些对象使用的算法可能经常改变,如果都将这些算法写到对象中,将会使对象变得异常复杂,而且有时候支持不适用的算法也是一个性能负担。所以我们需要一种能在运行时根据需要更改对象算法的方法(策略模式),使对象与算法解耦。
2.策略模式的应用场景
当对象的方法中出现像“if…else if…else”这种代码结构,随着时间的发展,需求可能会发生各种各样的变化,我们需要对“if…else if…else”这种代码进行修改或扩展,但是这样会违反“开放封闭原则”,我们应该想办法对原有的软件进行扩展,而不是进行修改。这时候,我们就可以用“策略模式”来应对这种需求的变化。
3.模式定义
定义一系列算法,把它们一个个封装起来,并且使它们可相互替换(变化)。该模式使得算法可独立于客户程序(稳定)而变化(扩展,子类化)。——《设计模式》GoF
4.结构图
5.要点总结
(1) Strategy及其子类为组件提供了一系列可重用的算法,从而可以使得类型在运行时方便地根据需要在各个算法之间进行切换。
(2) Strategy模式提供了用条件判断语句以外的另一种选择,消除条件判断语句,就是在解耦合。含有许多条件判断语句的代码通常都需要Strategy模式。
(3) 如果Strategy对象没有实例变量,那么各个上下文可以共享同一个Strategy对象,从而节省对象开销。
6.优缺点
(1)优点:适合类中的成员以方法为主,算法经常变动;简化了单元测试(因为每个 算法都有自己的类,可以通过自己的接口单独测试)。策略模式和简单工厂基本相同,但简单工厂模式只能解决对象创建问题,对于经常 变动的算法应使用策略模式。
(2)缺点:客户端要做出判断。
7.代码示例
//策略基类
class COperation
{
public:
int m_nFirst;
int m_nSecond;
virtual double GetResult()
{
double dResult = 0;
return dResult;
}
virtual ~COperation(){
}
};
//策略具体类—加法类
class AddOperation : public COperation
{
public:
AddOperation(int a,int b)
{
m_nFirst = a;
m_nSecond = b;
}
virtual double GetResult()
{
return m_nFirst + m_nSecond;
}
};
class Context
{
private:
COperation* op; //strategy的多态调用,可以是指针或者引用(不推荐),不能是一个对象,否则会失去多态性
public:
Context(COperation* temp)//这里可以和工厂方法结合使用,直接使用工厂类在类中生成所需的策略对象
{
op = temp;
}
double GetResult()
{
return op->GetResult();
}
};
//客户端
int main()
{
int a,b;
char c;
cin>>a>>b;
cout<<”请输入运算符:;
cin>>c;
switch(c)
{
case ‘+’:
Context *context=new Context(new AddOperation(a,b));
cout<<context->GetResult()<<endl;
break;
default:
break;
}
return 0;
}