C++策略模式
策略模式:
它定义了算法家族,分别封装起来,让它们之间可以相到替换,此模式用算法的变化不会影响到其它的客户。
此模式还是其实就是我们平常写的代码,其实设计模式就是告诉你如何写代码罢了,并不是什么搬来就可以用的方案,如果是这样,为鸟不直接写在库作框架调用就得了,因为它仅仅提供一种解决方案。它只是告诉你有与它相似需求的时候,代码该怎么写。这样写出来的代码它的扩展性好,容易维护,类之间的耦合度低。
策略模式迎合了几个面向对象的设计思想:
1、找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
2、多用组合,少用继承。
3、针对接口而不是实现编程。
引用《Head First 设计模式》中的例子:
假如我们要设一个鸭子类:
那么一般的想法就是:
在基类中,有fly(),swim(),quack()这些函数接口,然后在子类中只要实现这些接口就行了。但是问题来了,例如我们要实现一个“旱鸭子”和“橡皮鸭”。你会发现,感觉在设计上逻辑有点不太对了,像皮鸭会叫吗?它会有quack()或者fly()函数接口吗?而旱鸭子会有swim()方法?这些肯定是不对的。
问题在于这种设计思路不太符合:
2、多用组合,少用继承。
原则,都用继承就没有那么灵活了。
或者你会这么设计:
这样也许是个好设计,把fly()和swim单独弄出来作一个类,然后单独继承,这样设计倒是符合:
1、找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
但是Acton类本来应该也是Duck该有的,Action应该是属于Duck类。单独分开来继承,可能实现上没有太大的影响 ,但是从逻辑上好像也不太好,好像有人非得把你“五马分尸”。
所以总结下,这么设计:
也就是将Action作为Duck的成员,再在它自己的方法中调用Action中的接口。
voidDuck::peformfly(){
this->action.fly();
}
1 #include<iostream> 2 #include<string> 3 classStratery{ 4 public: 5 Stratery(){ 6 } 7 virtualvoidAlgorithmInterface(){ 8 std::cout<<"AlgorithmInterface"<<std::endl; 9 } 10 }; 11 classConcreteStrateryA:publicStratery{ 12 public: 13 virtualvoidAlgorithmInterface(){ 14 std::cout<<"ConcreteStrateryA"<<std::endl; 15 } 16 }; 17 classConcreteStrateryB:publicStratery{ 18 public: 19 virtualvoidAlgorithmInterface(){ 20 std::cout<<"ConcreteStrateryB"<<std::endl; 21 } 22 }; 23 classConcreteStrateryC:publicStratery{ 24 public: 25 virtualvoidAlgorithmInterface(){ 26 std::cout<<"ConcreteStrateryC"<<std::endl; 27 } 28 }; 29 classContext{ 30 private: 31 Stratery*stratery; 32 public: 33 Context(Stratery*_stratery):stratery(_stratery){ 34 } 35 voidContextInterface(){ 36 stratery->AlgorithmInterface(); 37 } 38 }; 39 int main(){ 40 Context contextA(newConcreteStrateryA()); 41 contextA.ContextInterface(); 42 Context contextB(newConcreteStrateryB()); 43 contextB.ContextInterface(); 44 Context contextC(newConcreteStrateryB()); 45 contextC.ContextInterface(); 46 }
上面的实现,就是使用了策略模式的经典用法。
ConcreteStrateryA
ConcreteStrateryB
ConcreteStrateryC
就是算法家族。这些算法之间是没有耦合的。这也是策略模式的要点之一。
可以说,策略模式就是用来封装算法,但是也可以扩展到所有其它与之要求相似的类。例如前面的Duck类,那么Duck类中封装的算法就是
Action了。