策略模式也是一种非常常用的设计模式,而且也不复杂。下面我们就来看看这种模式。
然后我们实现一个windmode 的类,作为 wind 系列的环境类:
最后客户端代码:
(这个实例网上也有人用命令模式实现。命令模式请看我后面的博客。把冷风,热风,无风作为一种命令。当然这是另外一种思路,也未尝不可。但是我觉得如果采用命令模式。类的个数会相应增加(增加系列的命令类),照成额外的开销。当添加一个新模式的时候,你需要添加的类过多。或多或少不是那么明智。所以我个人认为在这里策略模式更好一些。)
定义:策略模式定义了一系列的算法,并将每一个算法封装起来,而且使它们还可以相互替换。策略模式让算法独立于使用它的客户而独立变化。
角色:
抽象策略角色(Strategy): 抽象策略类。
具体策略角色(ConcreteStrategy):封装了继续相关的算法和行为。
环境角色(Context):持有一个策略类的引用,最终给客户端调用。
UML图:
事例: (该事例改编自一道网络设计模式面试题)
如现在你是一个设计师,你正在设计一种空调。但是你们的空调要支持3种模式。冷风模式(ColdWind), 热风模式(WramWind),无风模式(NoWind)。
当选择ColdWind模式,将输送冷风;当选择WarmWind模式,将输送热风;在选择NoWind模式时,空调什么都不做。你将考虑如何为空调设计应用程序?如果将来空调需要增加支持新的模式呢?
这道面试题,其实可以用各种模式实现,然而在这里我理解策略模式比较合适。我们将冷风模式,和热风模式以及无风模式可以理解为各种不同的算法。显然策略模式非常符合。
这里ColdWind, WramWind, NoWind 其实就是ConcreteStrategy。 IWnd 是抽象策略类。 所以我们开始这么封装我们策略类
- #include <iostream>
- using namespace std;
- #define free_ptr(p) \
- if(p) delete p; p = NULL;
- class IWind{
- public:
- virtual ~IWind(){};
- virtual void blowWind() = 0;
- };
- class ColdWind : public IWind{
- public:
- void blowWind(){
- cout<<"Blowing cold wind!"<<endl;
- };
- };
- class WarmWind : public IWind{
- public:
- void blowWind(){
- cout<<"Blowing warm wind!"<<endl;
- }
- };
- class NoWind : public IWind{
- public:
- void blowWind(){
- cout<<"No Wind!"<<endl;
- }
- };
然后我们实现一个windmode 的类,作为 wind 系列的环境类:
- class WindMode{
- public:
- WindMode(IWind* wind): m_wind(wind){};
- ~WindMode(){free_ptr(m_wind);}
- void blowWind(){
- m_wind->blowWind();
- };
- private:
- IWind* m_wind;
- };
最后客户端代码:
- int main(int argc, char* argv[])
- {
- WindMode* warmWind = new WindMode(new WarmWind());
- WindMode* coldWind = new WindMode(new ColdWind());
- WindMode* noWind = new WindMode(new NoWind());
- warmWind->BlowWind();
- coldWind->BlowWind();
- noWind->BlowWind();
- free_ptr(warmWind);
- free_ptr(coldWind);
- free_ptr(noWind);
- system("pause");
- return 0;
- }
(这个实例网上也有人用命令模式实现。命令模式请看我后面的博客。把冷风,热风,无风作为一种命令。当然这是另外一种思路,也未尝不可。但是我觉得如果采用命令模式。类的个数会相应增加(增加系列的命令类),照成额外的开销。当添加一个新模式的时候,你需要添加的类过多。或多或少不是那么明智。所以我个人认为在这里策略模式更好一些。)
总的说来策略模式:
优点:
1、 使用策略模式可以避免使用多重条件转移语句。多重转移语句不易维护。
2、 策略模式让你可以动态的改变对象的行为,动态修改策略
缺点:
1、客户端必须知道所有的策略类,并自行决定使用哪一个策略类。
2、类过多---策略模式造成很多的策略类,每个具体策略类都会产生一个新类。(这点可以通过享元模式来克服类过多)