策略模式是一種比較常用的設計模式,他主要體現在對象可以有某個行為,但是在不同的場景時用不同的實現方法!
在軟件開發中也常常遇到類似的情況,實現某一個功能有多種算法或者策略,我們可以根據環境或者條件的不同選擇不同的算法或者策略來完成該功能。如查找、排序等,一種常用的方法是硬編碼(Hard Coding)在一個類中,如需要提供多種查找算法,可以將這些算法寫到一個類中,在該類中提供多個方法,每一個方法對應一個具體的查找算法;當然也可以將這些查找算法封裝在一個統一的方法中,通過if…else…或者case等條件判斷語句來進行選擇。這兩種實現方法我們都可以稱之為硬編碼,如果需要增加一種新的查找算法,需要修改封裝算法類的源代碼;更換查找算法,也需要修改客戶端調用代碼。在這個算法類中封裝了大量查找算法,
該類代碼將較復雜,維護較為困難。如果我們將這些策略包含在客戶端,這種做法更不可取,將導致客戶端程序龐大而且難以維護,如果存在大量可供選擇的算法時問題將變得更加嚴重。
我們要做的就是如何把每個方法封裝在不同的類中,根據需要調用相應的方法!
在這裡同樣用兩個例子說明問題:
1:標准的策略模式實現方法!
2:經典的諸葛亮三策略指導趙雲東吳救主的故事!
先來看第一個,他簡單易懂的表明了策略模式的一般結構!
[cpp]
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;
}
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++實現這個場景:
[cpp]
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;
}
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;
}
這個例子很直觀吧,現在很多地方都用這個來解釋策略模式!又到飯點了,閃了