策略模式(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++》