策略模式
背景:假如现在要做一个税收的算法,这个税收的功能要支持多个国家,未来可能需要支持更多的国家。
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){ //更改
//...
}
//....
}
};
初始解法:就是定义一个枚举类,里面是不同国家,在SalesOrder类里面声明一个枚举对象,再算法中用if,else来匹配国家与对应的算法,当需要增加新的国家时,就在枚举类和CalculateTax添加。这样也违反了开闭原则,对扩展开放,对修改关闭。
这样的做法显然感觉很不好,就感觉应对变化很被动,不知道if else要加到什么时候,代码的可维护性很差。
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); //多态调用
//...
}
};
这样的写法就感觉很清楚,当有新的国家的税务算法时直接写一个类就行了,其他的代码不用改,达到了代码的复用,这里需要工厂模式的支持来实现多态,当需要调用不同国家的税务算法时,就实例化相应的对象。