可以看到 Strategy 模式和 Template 模式解决了类似的问题,也正如在 Template 模式中
分析的,Strategy模式和 Template 模式实际是实现一个抽象接口的两种方式:继承和组合之
间的区别。要实现一个抽象接口,继承是一种方式:我们将抽象接口声明在基类中,将具体
的实现放在具体子类中。组合(委托)是另外一种方式:我们将接口的实现放在被组合对象
中,将抽象接口放在组合类中。这两种方式各有优缺点,先列出来:
继承:
优点
1)易于修改和扩展那些被复用的实现。
缺点
1)破坏了封装性,继承中父类的实现细节暴露给子类了;
2) “白盒”复用,原因在 1)中;
3)当父类的实现更改时,其所有子类将不得不随之改变
4)从父类继承而来的实现在运行期间不能改变(编译期间就已经确定了)
组合 :
优点
1) “黑盒”复用,因为被包含对象的内部细节对外是不可见的;
2)封装性好,原因为 1) ;
3)实现和抽象的依赖性很小(组合对象和被组合对象之间的依赖性小) ;
4)可以在运行期间动态定义实现(通过一个指向相同类型的指针,典型的是抽象
基类的指针) 。
缺点
1)系统中对象过多。
从上面对比中我们可以看出,组合相比继承可以取得更好的效果,因此在面向对象
的设计中的有一条很重要的原则就是:优先使用(对象)组合,而非(类)继承(Favor Composition Over Inheritance)
1 //////////////Strategy.h////////////////////// 2 #pragma once 3 class Strategy 4 { 5 public: 6 virtual ~Strategy(); 7 Strategy(); 8 virtual void AlgrithmInterface() = 0 ; 9 protected: 10 private: 11 }; 12 13 class ConcreteStrategyA : public Strategy 14 { 15 public: 16 ~ConcreteStrategyA(); 17 ConcreteStrategyA(); 18 void AlgrithmInterface(); 19 protected: 20 private: 21 }; 22 23 class ConcreteStrategyB : public Strategy 24 { 25 public: 26 ~ConcreteStrategyB(); 27 ConcreteStrategyB(); 28 void AlgrithmInterface(); 29 protected: 30 private: 31 };
/////////////Strategy.cpp///////////////////////////////////////////////// #include "Strategy.h" #include <iostream> using namespace std; Strategy::~Strategy() { cout<<"~Strategy....."<<endl; } Strategy::Strategy() { } ConcreteStrategyA::~ConcreteStrategyA() { cout<<"~ConcreteStrategyA....."<<endl; } ConcreteStrategyA::ConcreteStrategyA() { } void ConcreteStrategyA::AlgrithmInterface() { cout<<"test ConcreteStrategyA....."<<endl; } ConcreteStrategyB::~ConcreteStrategyB() { cout<<"~ConcreteStrategyB....."<<endl; } ConcreteStrategyB::ConcreteStrategyB() { } void ConcreteStrategyB::AlgrithmInterface() { cout<<"test ConcreteStrategyB....."<<endl; }
///////////Context.h/////////////////////////// #pragma once class Strategy ; class Context { public: ~Context(); Context(Strategy* stg); void DoAction(); protected: private: Strategy* _stg ; };
//////////Context.cpp/////////////////////////////////// #include "Context.h" #include "Strategy.h" #include <iostream> Context::Context(Strategy* stg) { _stg = stg ; } Context::~Context() { if (_stg != NULL) { delete _stg ; } } void Context::DoAction() { _stg->AlgrithmInterface(); }
/////////////main.cpp////////////////////////////////// #include "Context.h" #include "Strategy.h" #include <iostream> int main() { Strategy* ps = new ConcreteStrategyA(); Context* pc = new Context(ps); pc->DoAction(); delete pc; getchar(); return 0 ; }