Strategy模式中文是策略模式,是对算法的封装,即使是一个简单的计算行为,如果需要实现多态性,并为了扩展容易目的,我们需要将其抽象出来,定义为接口,由于充分的利用OOP的多态性,在调用该行为时,其具体实现是运行期决定。以税收计算为例,假定税收分为个人税和企业税,根据Strategy模式,我们应该把税收策略抽象为接口ITaxStrategy。
Public Interfece ITaxStrategy
{
Double Calculate(double income);
}
//把各种税收策略实现该接口
Public double P_TaxStrategy:ITaxStrategy
{
public double Calculate(double income)
{//实现
}
}
public double E_TaxStrategy:ITaxStrategy
{
public double Calculate(double income)
{//实现
}
}
//有一个公共类提供税收的相关操作,计算所得税的方法
Public class TaxOp
{
private ITaxStrategy Strategy;
public TaxOp(ITaxStrategy Strategy )
{
this.Strategy=Strategy;
}
public double GetTax(double income)
{
return Strategy.Calculate(income);
}
}
//客户端调用
public class Application
{
private void Main(string[] args)
{
TaxOp top=new TaxOp(new p_TaxStrategy());
Console.WriteLine("个人所得税是:{0}",top.GetTax(1000));
}
}
这是一种典型的面向对象的设计思路。然而,对于一些简单的算法行为,我们也可以利用delegate委托的方式,来实现以上的设计,它虽然更近似于面向过程的设计,但其扩展性同样灵活。如果算法的逻辑不复杂,且算法的实现处于某种待定的状态,也许使用委托会比Strategy模式更方便。
我们同样利用上述的例子,只是将原来抽象出来的接口修改为委托:
public delegate double CalculateTax(double income);
对于个人所得税和企业所得税的实现,相应修改为:
public class Tax
{
public static double CalculatePersonalTax(double income)
{
//实现;
}
public static double CalculateEnterpriseTax(double income)
{
//实现;
}
}
税收的公共类则修改如下:
public class TaxOp
{
private CalculateTax calDel;
public TaxOp(CalculateTax calDel)
{
this.calDel = calDel;
}
public double GetTax(double income)
{
return calDel(income);
}
}
客户端的调用:
public class App
{
public static void Main(string[] args)
{
TaxOp op = new TaxOp(new CalculateTax(Tax.CalculatePersonalTax));
Console.WriteLine("个人所得税是:{0}", op.GetTax(1000));
}
}
从这两个实现方案来看,代码是大同小异的,但设计思想则迥然不同。它是面向对象和面向过程的区别,前者是将行为封装为对象,而后者则直接对方法进行操作,同时又利用delegate委托来实现扩展。个人意见,我还是倾向于第一种方案,但后者至少也提供了一种思路。尤有甚者,我们也可以将委托理解为一种特殊的抽象,因为其本质是函数指针,它代表了一簇函数,从而对具有相同特性的行为进行了普遍意义的抽象。也许,这样可以促进对委托的理解。