背景
在软件构建过程中,某些对象使用的算法可能多种多样,常常会改变
如果将这些算法都编码到对象中,将会使对象变得异常复杂,
而且有使用支持不适用的算法也是一个性能负担
问题
如何在运行时更具需要透明地改变对象地算法,将算法和对象本身解耦,从而避免上述问题
模式定义
定义一系列算法,把他们封装起来,并且使他们可以相互替换,该模式使得算法可以独立于它的客户程序而变化。
代码
enum TaxBase
{
CN_tax,
US_tax,
DE_tax
};
class SaleOrder
{
public:
TaxBase tax;
SaleOrder()
{
//构造函数
}
~SaleOrder()
{
//析构函数
}
double CalculateTax()
{
if (tax == CN_tax)
{
//........
}
if (tax == US_tax)
{
//......
}
if (tax == DE_tax)
{
//..........
}
}
private:
};
/*
* 上述代码中,计算了中国、美国、德国的物品税率,那现在如果需要加入法国、英国的税率怎么弄呢?
* 或许会在TaxBase上增加UK_tax,FR_tax,然后在CalculateTax函数中增加两个if语句
* 但是这种方式就违背了“对新增开放,对修改封闭的原则”而且很多的if语句也会导致程序运行变慢。
*/
使用策略模式地改进代码
class TaxStrategy
{
public:
virtual double Calculate(int data) = 0;
virtual ~TaxStrategy() {}
};
class CnTax:TaxStrategy
{
public:
CnTax()
{
// 构造函数
}
~CnTax()
{
// 析构函数
}
double Calculate(int data)
{
// 中国的汇率计算
}
private:
};
class UsTax :public TaxStrategy
{
public:
UsTax()
{
// 构造函数
}
~UsTax()
{
// 析构函数
}
double Calculate(int data)
{
// 美元的汇率计算
}
};
class SaleOrder
{
private:
TaxStrategy* strategy;
public:
SaleOrder(TaxStrategy taxStrategy)
{
this->strategy = &taxStrategy;
}
double CalculateTax()
{
int data = 10;
this->strategy->Calculate(data);
}
};
总结
策略及其子类为组件提供了一系列可以重用的算法,从而可以使得类型在运行时方便地根据需要在各个算法之间进行切换
策略模式提供了条件判断语句之外地另外一种选择,当程序有多个条件判断语句时可以用策略模式解除耦合
如果策略模式对象没有实例变量,那么各个上下文可以共享一个策略对象,从而节省对象开销