模式动机(Strategy Pattern):在完成一个任务时可能有多种方式,具体使用哪种方式最有效,需要视条件而定,不同条件下所选择的策略也有所不同,这就需要在一个环境中对当前的情况做出各种判断,在程序设计中表现为分支结构的实现,即在一个环境类中通过不同分支来决定使用哪种策略,这种将实现策略与当前环境都封装在一个类中的设计方法称为硬编码。
硬编码有如下缺点:其一,如果环境发生改变需要增加条件判断时,需要修改当前环境类以增加分支;其二,在实时性方面,也许客户不愿意支持它们不需要的分支算法,因为分支判断造成一定的延时;再者,将实现模块与环境状态混合在一起,不仅难以理解,而且也更加难以维护。
鉴于上述原因,可以使用策略模式来解决。策略模式思想非常简单,却十分有效。其将每一个策略都封装为一个具体类,将各个策略的公共接口抽取出来封装为一个策略接口,令环境类和策略接口交互即可。这样,如果客户想添加新的策略方法,只需添加一个策略接口的实现类即可,而环境类完全不必关注到底该使用哪个策略,因为在它看来,所有的策略方法都是一样的。
1 #ifndef SP_H 2 #define SP_H 3 #include <iostream> 4 using namespace std; 5 6 /* 7 抽象策略接口 8 */ 9 class Strategy 10 { 11 public: 12 virtual ~Strategy(){ } 13 virtual void Algorithm() = 0; 14 }; 15 16 /* 17 具体策略类 18 */ 19 class ConcreteStrategyA : public Strategy 20 { 21 public: 22 virtual void Algorithm() 23 { 24 cout << "使用策略 A" << endl; 25 } 26 }; 27 class ConcreteStrategyB : public Strategy 28 { 29 public: 30 virtual void Algorithm() 31 { 32 cout << "使用策略 B" << endl; 33 } 34 }; 35 36 /* 37 环境上下文类 38 */ 39 class Context 40 { 41 public: 42 Context(Strategy* s) : strategy(s){ } 43 void Execute() 44 { 45 strategy->Algorithm(); 46 } 47 48 private: 49 Strategy* strategy; 50 }; 51 52 #endif // SP_H
1 #include "bt_策略模式.h" 2 3 int main() 4 { 5 cout << "***** 策略模式测试 *****" << endl; 6 Strategy* strategy = new ConcreteStrategyA; 7 Context* context = new Context(strategy); 8 context->Execute(); 9 10 delete context; 11 delete strategy; 12 13 return 0; 14 }
:: 策略模式解决了将实现方法硬编码到环境类中的问题,使得新增策略方法时不需要修改原有代码,增加了系统的可扩展性。但是同时如果系统中有很多不同的策略,而每个策略又比较简单,此时应用策略模式会使得系统中策略类的数量非常庞大。因此,策略模式比较适合后期扩展,并不适合解决方案比较固定且简单的设计。
:: 策略模式需要依赖于客户选择具体的策略方式,这增加了客户端编码的难度。