策略模式(Strategy):它定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化,不会影响到使用算法的客户。
上面是《大话设计模式》中给出的定义,感觉这个概念给的不好,看了之后不能完全清晰明白该模式(可能自己水平太水的原因吧)。在《effective c++》中指出,策略模式是virtual 函数的替换方法。仔细想想也差不多。如果想在不同的类中实现不同的算法,那么在基类中定义一个virtual函数,派生类给出不同的实现即可。这里出现一个问题,如果要实现的算法太多(算法参数、返回值等不同),那么需要在基类中都进行virtual声明,在具体的类中给出具体函数的实现。那么每个派生类都需要继承那么多virtual 函数(而且多数没用),派生类好臃肿啊。有人给出派生类减肥法,工厂模式,其实就是每个算法给出一个实现类外加多态的使用;别的方法,那就是每个算法实现一个类,把这个类传入到具体的过程类中,让算法类作为过程类的一个属性,可以根据要求进行设置,当然这个算法跟工厂模式有些相似处。(后面有两者关系图)
先描述一下应用场景吧,设计商场收费软件,要求能够满足,不同的打折要求、不同的满几百送几百的返利要求。比如:店庆打8折,国庆节满300送100;
下面看一下,工厂模式和策略模式关系图,看一下他们之间的差别:
工厂模式:
策略模式:
下面看一下传统的策略模式的实现代码:
#include<iostream>
#include<string>
using namespace std;
class CashSuper
{
public:
virtual double acceptCash(double money) = 0;
};
class CashNormal : public CashSuper
{
public :
double acceptCash(double money)
{
return money;
}
};
class CashRebate : public CashSuper
{
public:
CashRebate(double d = 1) : moneyRebate(d)
{}
double acceptCash(double money);
private:
double moneyRebate;
};
double CashRebate::acceptCash(double money)
{
return money * moneyRebate;
}
class CashReturn : public CashSuper
{
public:
CashReturn(double mc = 0.0, double mr = 0.0) : moneyCondition(mc), moneyReturn(mr)
{}
double acceptCash(double money);
private:
double moneyCondition;
double moneyReturn;
};
double CashReturn::acceptCash(double money)
{
double result = money;
if (money > moneyCondition)
result = money - (int)(money / moneyCondition)* moneyReturn;
return result;
}
class CashContext
{
public :
CashContext(CashSuper *cashuper) : cs(cashuper)
{}
double GetResult(double money);
private:
CashSuper *cs;
};
double CashContext::GetResult(double money)
{
return cs->acceptCash(money);
}
上面的是传统策略模式的实现代码,但是只是个框架,很好看,不中用;没有具体环境执行。
下面是策略模式和工厂模式结合的代码,情景如上所述:其中1代表:正常模式收费; 2代表:满300送100; 3代表:打8折。
将上面的CashContext替换成ConcreteCashContext就可以直接运行了。
class ConcreteCashContext
{
public:
ConcreteCashContext(int type);
double GetResult(double money);
private:
CashSuper *cs;
};
double ConcreteCashContext::GetResult(double money)
{
return cs->acceptCash(money);
}
ConcreteCashContext::ConcreteCashContext(int type)
{
switch(type)
{
case 1:
cs = new CashNormal();
break;
case 2:
cs = new CashReturn(300,100);
break;
case 3:
cs = new CashRebate(0.8);
break;
default:
cout << " cant not recognize the type " << endl;
}
}
int main(int argc, char **argv)
{
ConcreteCashContext *ccc = new ConcreteCashContext(2);
double money = 850.45;
cout << " The moeny is : " << money << endl;
cout << "you have to pay : " << ccc->GetResult(money) << endl;
system("pause");
return 0;
}
参考:
1、《大话设计模式》
2、《effective c++》