策略模式是一種比較常用的設計模式,他主要體現在對象可以有某個行為,但是在不同的情境時用不同的實現方法!
在軟體開發中也常常遇到類似的情況,實現某一個功能有多種演算法或者策略,我們可以根據環境或者條件的不同選擇不同的演算法或者策略來完成該功能。如尋找、排序等,一種常用的方法是寫入程式碼(Hard Coding)在一個類中,如需要提供多種尋找演算法,可以將這些演算法寫到一個類中,在該類中提供多個方法,每一個方法對應一個具體的尋找演算法;當然也可以將這些尋找演算法封裝在一個統一的方法中,通過if…else…或者case等條件判斷語句來進行選擇。這兩種實現方法我們都可以稱之為寫入程式碼,如果需要增加一種新的尋找演算法,需要修改封裝演算法類的原始碼;更換尋找演算法,也需要修改用戶端調用代碼。在這個演算法類中封裝了大量尋找演算法,
該類代碼將較複雜,維護較為困難。如果我們將這些策略包含在用戶端,這種做法更不可取,將導致用戶端程式龐大而且難以維護,如果存在大量可供選擇的演算法時問題將變得更加嚴重。
我們要做的就是如何把每個方法封裝在不同的類中,根據需要調用相應的方法!
在這裡同樣用兩個例子說明問題:
1:標準的策略模式實現方法!
2:經典的諸葛亮三策略指導趙雲東吳救主的故事!
先來看第一個,他簡單易懂的表明了策略模式的一般結構!
class StrategyInterface //抽象的介面{ public: virtual void execute() = 0;}; class ConcreteStrategyA: public StrategyInterface //方法A,實現了介面,下同{ public: virtual void execute() { cout << "Called ConcreteStrategyA execute method" << endl; }}; class ConcreteStrategyB: public StrategyInterface{ public: virtual void execute() { cout << "Called ConcreteStrategyB execute method" << endl; }}; class ConcreteStrategyC: public StrategyInterface{ public: virtual void execute() { cout << "Called ConcreteStrategyC execute method" << endl; }}; class Context { //主操作類 private: StrategyInterface *_strategy; public: Context(StrategyInterface *strategy):_strategy(strategy) { } void set_strategy(StrategyInterface *strategy) { _strategy = strategy; } void execute() { _strategy->execute(); }}; int main(int argc, char *argv[]){ ConcreteStrategyA concreteStrategyA; ConcreteStrategyB concreteStrategyB; ConcreteStrategyC concreteStrategyC; Context contextA(&concreteStrategyA); Context contextB(&concreteStrategyB); Context contextC(&concreteStrategyC); contextA.execute(); //函數內部利用多態調用相應的方法! contextB.execute(); contextC.execute(); contextA.set_strategy(&concreteStrategyB); contextA.execute(); contextA.set_strategy(&concreteStrategyC); contextA.execute(); return 0;}
上述的例子已經足以明白策略模式的一般實現方式了,接下來看第二個問題
首先這個情境裡有三個妙計,一個錦囊,趙雲是開啟錦囊 方法的執行者,所以應該在主函數,UML圖如下所示
接下裡看看如何用C++實現這個情境:
class IStrategy {public:virtual void Operator() = 0;};class Fun1:public IStrategy{void Operator(){cout<<"找喬國老幫忙,讓孫權不殺劉備"<<endl;}};class Fun2:public IStrategy{void Operator(){cout<<"求吳國太開個綠燈,允許存取"<<endl;}};class Fun3:public IStrategy{void Operator(){cout<<"找孫夫人斷兵,爭取逃走的時間"<<endl;}};class ContualClass{private:IStrategy * m_pSrategy;public:ContualClass() {}ContualClass(IStrategy *pirevt){this->m_pSrategy = pirevt;}void Operator(){m_pSrategy->Operator();}};int main(){//剛剛到吳國的時候拆第一個cout<<("-----------剛剛到吳國的時候拆第一個-------------")<<endl; ContualClass *context = new ContualClass(new Fun1()); //拿到妙計context->Operator(); //拆開執行//劉備樂不思蜀了,拆第二個了cout<<("-----------劉備樂不思蜀了,拆第二個了-------------")<<endl;context = new ContualClass(new Fun2()); context->Operator(); //執行了第二個錦囊了//孫權的小兵追了,咋辦?拆第三個cout<<("-----------孫權的小兵追了,咋辦?拆第三個")<<endl;context = new ContualClass(new Fun3()); context->Operator(); //孫夫人退兵system("pause");return 0;}
這個例子很直觀吧,現在很多地方都用這個來解釋策略模式!又到飯點了,閃了