策略模式(Strategy)
1. 策略模式:面对算法时常改动时
定义一系列的算法家族,把每一个算法分别封装起来, 并且使它们可相互替换。本模式使得算法的变化,不会影响到使用算法的客户,且不需要修改策略类。
2.适用性:什么情况下使用策略模式
(1)如果在一个系统里面有许多类,它们之间的区别仅在于它们的行为,那么使用策略模式可以动态地让一个对象在许多行为中选择一种行为。
(2) 一个系统需要动态地在几种算法中选择一种。那么这些算法可以包装到一个个的具体算法类里面,而这些具体算法类都是一个抽象算法类的子类。换言之,这些具体算法类均有统一的接口,由于多态性原则,客户端可以选择使用任何一个具体算法类,并只持有一个数据类型是抽象算法类的对象。
(3)一个系统的算法使用的数据不可以让客户端知道。策略模式可以避免让客户端接触到的复杂的只与算法有关的数据。
(4) 如果一个对象有很多的行为,如果不用恰当的模式,这些行为就只好使用多重的条件选择语句来实现。此时,使用策略模式,把这些行为转移到相应的具体策略类里面,就可以避免使用难以维护的多重条件选择语句,并体现面向对象设计的概念。、
下面不妨举几个在实际应用中已经使用策略模式的例子:
例1:
想必经常编程序的人基本上都用过这个函数吧publicvirtual voidSort (IComparer comparer),可以看到Sort方法接收一个IComparer类型的参数,那么这个IComparer接口是做什么用的呢?其实是用来确定排序方式的,例如是从大到小排序还是从小到大排序等。这是conpare具体取值就是动态确定的,并且是一系列算法的集合,所以非常适合策略模式,实际上使用的也是策略模式。
例2:
还比如在玩“极品飞车”这款游戏,那么游戏对车的轮胎是可以更换的,不同的轮胎在高速转弯时有不同的痕迹样式,那么针对“汽车”的配件“轮胎”就要可以变化,而且轮胎和轮胎之间是可以相互替换的,这就是典型的要应用“策略模式”的场景!
3.实例:《大话设计模式》------商场促销收银软件。
#include <iostream>
#include <cmath>
#include <string>
using namespace std;
//策略模式
class CashSuper
{
public:
virtual double acceptMoney(double money)=0;
};
class CashNormal:public CashSuper
{
public:
double acceptMoney(double money)
{
return money;
}
};
class CashRebate:public CashSuper
{
private:
double discount;
public:
CashRebate(double dis)
{
discount=dis;
}
double acceptMoney(double money)
{
return money*discount;
}
};
class CashReturn:public CashSuper
{
private:
double moneyCondition;
double moneyReturn;
public:
CashReturn(double mc,double mr)
{
moneyCondition=mc;
moneyReturn=mr;
}
double acceptMoney(double money)
{
double result=money;
if(money>=moneyCondition)
{
result=money-floor(money/moneyCondition)*moneyReturn;
}
return result;
}
};
class CashContext
{
private:
CashSuper *cs;
public:
CashContext(CashSuper *cs)
{
this->cs=cs;
}
double getResult(double money)
{
return cs->acceptMoney(money);
}
};
int main()
{
CashSuper *cs;
CashContext *cc;
double money;
money=1000;
cs=new CashRebate(0.8);
cc=new CashContext(cs);
cout<<cc->getResult(money)<<endl;
money=1000;
cs=new CashNormal();
cc=new CashContext(cs);
cout<<cc->getResult(money)<<endl;
return 0;
}
3.策略模式和简单工厂模式联手
基础的策略模式并不是最佳的方法,其实只要和简单工厂模式结合相使用,就能使得客户端“认识”的类减少(只需要认识Context类),进一步减少耦合性,并且也使得客户端中所要做出的逻辑判断(到底用哪个具体策略)转移到工厂类中。这里我们把Context作为工厂类就可以了。看看代码吧:
class CashContext
{
private:
CashSuper *cs;
public:
CashContext(string str)
{
if(str=="正常收费")
{
cs=new CashNormal();
}
else if(str=="打折")
{
cs=new CashRebate(0.9);
}
else if(str=="满送")
{
cs=new CashReturn(300,200);
}
}
double getResult(double money)
{
return cs->acceptMoney(money);
}
};
int main()
{
double money=1000;
CashContext *cc=new CashContext("打折");
cout<<cc->getResult(money);
return 0;
}
本文参考网上博客及大话设计模式总结。