这里以一个栗子来解释策略模式,当周末来临,作为程序猿的你是打算出去浪呢,还是继续睡觉,还是去加班呢(当然是……)。下面用代码来展示:
#include <iostream> using namespace std; class Strategy{ //策略基类 public: Strategy(){} virtual ~Strategy(){} //基类的析构函数最好是虚析构函数 virtual void Choose() = 0; }; class Play: public: Strategy{ //游玩 public: Play(){} ~Play(){} void Choose(){ cout<<"Play ^_^"<<endl; } }; class Sleep: public: Strategy{ //睡觉 public: Sleep(){} ~Sleep(){} void Choose(){ cout<<"Sleep ~_~"<<endl; } }; class Work: public: Strategy{ //工作 public: Work(){} ~Work(){} void Choose(){ cout<<"Work >_<"<<endl; } }; class Weekend{ //周末 public: Weekend(Strategy *_strategy):ch_strategy(_strategy){ } ~Weekend(){ delete ch_strategy; } void Choose(){ ch_strategy->Choose(); } private: Strategy *ch_strategy; }; int main(){ Weekend *week_play = new Weekend(new Play()); Weekend *week_sleep = new Weekend(new Sleep()); Weekend *week_work = new Weekend(new Work()); week_play->Choose(); week_sleep->Choose(); week_work->Choose(); delete week_play; delete week_sleep; delete week_work; return 0; }接下来我们看一下策略模式的定义:
它定义了一系列的算法,并将每一个算法封装起来,而且使他们还可以相互替换。策略模式让算法变化不会影响到使用算法的客户。
从上面的代码中可以看出,即使你周末有更多的选择,如看电影、打豆豆、做头发等等,只需要继承策略类就可以,你只要去选择就可以。
包含的角色:
抽象策略角色(Strategy):抽象策略类;具体策略角色(ConcreteStrategy):封装了继承相关的算法和行为;环境角色(Context):持有一个策略类的引用,最终给客户端调用(相当于上面代码中的Weekend);然后看一下它的UML图(以上面的程序为基础):
图 1 策略模式结构
优点:
简化了单元测试,因为每个算法都有自己的类,可以通过自己的接口单独测试;避免程序中使用多重条件转移语句,使系统更灵活,并易于扩展; 遵守大部分GRASP原则和常用设计原则,高内聚、低偶合;策略模式是一种定义一系列算法的方法,从概念上来看,所有这些算法完成的都是相同的工作,只是实现不同,它可以以相同的方式调用所有的算法,减少了各种算法类与使用算法类之间的耦合。缺点:
因为每个具体策略类都会产生一个新类,所以会增加系统需要维护类的数量;在基本的策略模式中,选择所用具体实现的职责由客户端对象承担,并转给策略模式的Context对象;进一步看一下策略模式与简单工厂模式的结合:
#include <iostream> using namespace std; class Strategy{ //策略基类 public: Strategy(){} virtual ~Strategy(){} //基类的析构函数最好是虚析构函数 virtual void Choose() = 0; }; class Play: public Strategy{ //游玩 public: Play(){} ~Play(){} void Choose(){ cout<<"Play ^_^"<<endl; } }; class Sleep: public Strategy{ //睡觉 public: Sleep(){} ~Sleep(){} void Choose(){ cout<<"Sleep ~_~"<<endl; } }; class Work: public Strategy{ //工作 public: Work(){} ~Work(){} void Choose(){ cout<<"Work >_<"<<endl; } }; class Weekend{ //周末 public: Weekend(int type); ~Weekend(){} void My_Hobby(){ ch_strategy->Choose(); } private: Strategy *ch_strategy; }; Weekend::Weekend(int type){ switch(type){ case 0: ch_strategy = new Play(); break; case 1: ch_strategy = new Sleep(); break; case 2: ch_strategy = new Work(); break; default: ch_strategy = NULL; break; } } int main(){ Weekend *week_play = new Weekend(0); Weekend *week_sleep = new Weekend(1); Weekend *week_work = new Weekend(2); week_play->My_Hobby(); week_sleep->My_Hobby(); week_work->My_Hobby(); delete week_play; delete week_sleep; delete week_work; return 0; }
