目录
4.3 如何面对大量的if...else或者switch...case
0.阅读
1.模式简介
1.1 策略模式的动机(Motivation)
在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都编码到对象中,将会使对象变得异常复杂;而且有时候支持不使用的算法也是一个性能负担.如何在运行是根据需要透明地更改对象的算法?将算法与对象本身解耦,从而避免上述问题?
1.2 模式定义
定义一些列算法,把它们一个个封装起来,并且使得它们可以互相替换(变化),该模式使得算法可以独立于使用它的客户程序(稳定)而变化(拓展,子类化).
---《设计模式》GoF
1.3 图解
2.原来的时候面对变化
// 违反开闭原则
// 开闭原则: 对扩展开放,对修改关闭
#include <iostream>
using namespace std;
enum TaxBase{
CN_Tax,
US_Tax,
DE_Tax,
FR_Tax // 更改
};
class SalesOrder{
public:
TaxBase tax;
public:
void CalculateTax(){
if(tax == CN_Tax){
cout << "这个是中国的税法计算方法"<< endl;
}
else if(tax == US_Tax){
cout << "这个是美国的税法计算方法"<< endl;
}
else if(tax == DE_Tax){
cout << "这个是德国的税法计算方法"<< endl;
}ss
else if(tax == FR_Tax){ // 更改
cout << "这个是法国的税法计算方法"<< endl;
}
}
};
int main(){
SalesOrder obj_tax_cal;
obj_tax_cal.tax = CN_Tax;
obj_tax_cal.CalculateTax();
}
3.策略模式下面对变化
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){
//.........
}
};
// SalesOrder这个类是不再变化的,不需要再编码的,得到了复用性.
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); //多态调用
//...
}
};
4.一些注意点
4.1 策略模式的缺点与优点
类变多了.策略模式一样要有判断,判断转移到工厂中去了,后面的人看不见工厂就不会对
工厂有错误修改.
4.2 真正的复用
真正的复用是编译之后,测试之后,部署之后,再需要改需求的时候,代码是不需要改变的,
是二进制意义上的单位复用,而不是源代码的片段级别的复用.在一段代码底下补充一些代码往往会引入一些bug,
所以在源代码级别的复制粘贴我们是不推荐的,我们压根不将其称为复用性.
4.3 如何面对大量的if...else或者switch...case
当你的代码中出现了大量的if...else或者switch...case的时候,你是否嗅到了bad smell也许你
就该要好好的考虑是不是可以用策略模式了.当然如果if...else或者switch...case出现的情况是
固定不变的,那么这种情况下,也不一定就要用策略模式来进行编码设计.
5.总结
1.Strategy及其子类为组件提供了一系列可重用的算法,从而可以使得类型在运行时方便地根
据需要在各个算法之间进行切换。
2.Strategy模式提供了用条件判断语句以外的另一种选择,消除条件判断语句,就是在解耦合.
含有许多条件判断语句的代码通常都需要Strategy模式.
3.如果Strategy对象没有实例变量,那么各个上下文可以共享同一个Strategy对象,从而节省
对象开销。