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