设计模式之strategy模式(C++实现)
策略模式是一种比较常用的设计模式,他主要体现在对象可以有某个行为,但是在不同的场景时用不同的实现方法!
在软件开发中也常常遇到类似的情况,实现某一个功能有多种算法或者策略,我们可以根据环境或者条件的不同选择不同的算法或者策略来完成该功能。如查找、排序等,一种常用的方法是硬编码(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; }
这个例子很直观吧,现在很多地方都用这个来解释策略模式!又到饭点了,闪了