策略模式(strategy pattern)
策略模式:
定义了一个算法族,分别把每个算法封装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。
结构图:
C++实现:
class calculateStrategy { public: virtual int calculate(int value1, int value2) = 0; }; class Plus : public calculateStrategy { public: int calculate(int value1, int value2) { return value1 + value2;} }; class Minus : public calculateStrategy { public: int calculate(int value1, int value2) { return value1 - value2;} }; class Calculator { private: calculateStrategy *cs; public: Calculator(calculateStrategy *strategy): cs(strategy) {} int calculate(int value1, int value2) { return cs->calculate(value1, value2); } void setStrategy(calculateStrategy *strategy) { cs = strategy; }; ~Calculator() { delete cs; } }; int main() { calculateStrategy *strategy = new Plus; Calculator cal(strategy); cout << cal.calculate(1, 2) << endl; delete strategy; strategy = new Minus; cal.setStrategy(strategy); cout << cal.calculate(1, 2) << endl; //delete strategy; }
策略模式使用了一个非常重要的设计原则:多用组合,少用继承。组合和继承的简单比较如下:
1. 在继承关系中,父类的内部细节对子类可见。父类通常至少定义了子类的部分行为,父类的任何改变都可能影响子类行为。 而在组合关系中,整体类和局部类之间不会去关心各自的实现细节,即它们之间的实现细节是不可见的。 2. 继承关系在编译时刻静态定义,子类无法在运行时刻改变从父类继承来的实现。组合关系在运行时刻动态定义,支持动态改变。
再贴张对比图:
组 合 关 系 |
继 承 关 系 |
优点:不破坏封装,整体类与局部类之间松耦合,彼此相对独立 |
缺点:破坏封装,子类与父类之间紧密耦合,子类依赖于父类的实现,子类缺乏独立性 |
优点:具有较好的可扩展性 |
缺点:支持扩展,但是往往以增加系统结构的复杂度为代价 |
优点:支持动态组合。在运行时,整体对象可以选择不同类型的局部对象 |
缺点:不支持动态继承。在运行时,子类无法选择不同的父类 |
优点:整体类可以对局部类进行包装,封装局部类的接口,提供新的接口 |
缺点:子类不能改变父类的接口 |
缺点:整体类不能自动获得和局部类同样的接口 |
优点:子类能自动继承父类的接口 |
缺点:创建整体类的对象时,需要创建所有局部类的对象 |
优点:创建子类的对象时,无须创建父类的对象 |
reference: