Strategy
策略模式
应该尽量使用扩展的方式,而不是修改源代码,例如下面这样要增加新的国家的税法就只能去源代码里面改枚举类型
enum TaxBase {
CN_Tax,
US_Tax,
DE_Tax,
FR_Tax //更改
};
class SalesOrder{
TaxBase tax;
public:
double CalculateTax() {
//...
if (tax == CN_Tax) {
//CN***********
}
else if (tax == US_Tax) {
//US***********
}
else if (tax == DE_Tax) {
//DE***********
}
else if (tax == FR_Tax) { //更改
//...
}
//....
}
};
我们修改上面代码的方法是使用策略方法,其核心原则是虚类在创建时动态绑定,至于绑定的对象,我们使用工厂方法来生产对应的策略
class TaxStrategy {
public:
virtual double Calculate(const Context& context)=0;
virtual ~TaxStrategy() {}
};
class CNTax : public TaxStrategy {
public:
virtual double Calculate(const Context& context) {
//***********
}
};
class USTax : public TaxStrategy {
public:
virtual double Calculate(const Context& context) {
//***********
}
};
class DETax : public TaxStrategy {
public:
virtual double Calculate(const Context& context) {
//***********
}
};
//扩展
//*********************************
class FRTax : public TaxStrategy {
public:
virtual double Calculate(const Context& context){
//.........
}
};
class SalesOrder {
private:
TaxStrategy* strategy;
public:
SalesOrder(StrategyFactory* strategyFactory) {
this->strategy = strategyFactory->NewStrategy();
}
~SalesOrder() {
delete this->strategy;
}
public double CalculateTax() {
//...
Context context();
double val = strategy->Calculate(context); //多态调用
//...
}
};
这样要增加新的税法的时候就再新文件中写个子类继承TaxStrategy
就行,源代码可以不用修改
模式定义
定义一系列算法,把它们一个个封装起来,并且使它们可互相替换(变化),该模式使得算法可独立于使用它的客户程序(稳定)而变化(扩展,子类化)
- Strategy 及其子类为组件提供了一系列可重用的算法,从而可以使得类型在运行时方便地根据需要再各个算法之间进行切换
- Strategy 模式提供了用条件判断语句以外的另一种选择,消除条件判断语句,就是在解耦合,含有许多条件判断语句的代码通常都需要 Strategy 模式
- 如果 Strategy 对象没有实例变量,那么各个上下文可以共享同一个 Strategy 对象,从而节省对象开销