Strategy模式是对算法的封装。即使是一个计算行为,如果其实现有其多样性,为达到易扩展的目的,我们可以将其抽象出来,以接口的形式来定义。利用了面向对象的多态性,在运行时,可以灵活的变更这个算法的具体实现。
以税收计算为例,假定税收策略分为个人所得税,和企业所得税。根据策略模式,将税收策略抽象为接口ITaxStrategy:
public interface ITaxStrategy
{
double Calculate(double income);
}
各种税收策略均实现该类。
public class PeronalTaxStrategy:ITaxStrategy
{
public double Calculate(double income)
{
//实现;
}
}
public class EnterpriseTaxStrategy:ITaxStrategy
{
public double Calculate(double income)
{
//实现;
}
}
如果此时有一个公共的类,提供税收的相关操作,其中就包括计算所得税的方法:
public class TaxOp
{
private ITaxStrategy strategy;
public TaxOp(ITaxStrategy strategy)
{
this.strategy = strategy;
}
public void ChangeStrategy(ITaxStrategy strategy)
{
this.strategy = strategy
}
public double GetTax(double income)
{
return strategy.Calculate(income);
}
}
客户端调用:
public class App
{
public static void Main(string[] args)
{
TaxOp op = new TaxOp(new PersonalTaxStrategy());
Console.WriteLine(“The Personal Tax is :{0}”, op.GetTax(1000));
}
}
为了达到上面的目的,我们也可以将原来抽象出来的接口修改为委托:
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(Calculate 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(“The Personal Tax is :{0}”, op.GetTax(1000));
}
}
这两种方案的目的都是相同的,就是将算法和算法的使用者分开解耦,达到松耦合高聚合的目的。有过c/c++使用经验的人,可能将这两种方案的区别看成一个是是面向对象的,一个是面向过程的,前者(使用Interface class 或者 abstract class作为策略父类)是将方法封装在对象内部,而后者(使用Delegate)则直接对方法进行操作,同时又利用delegate委托来实现扩展,为什么呢,那是因为Delegate的使用方法和和c/c中的++函数指针是一样的,它的行为本质和函数指针一样。但是从OO来看,Delegate可以看成是对具有相同特性的行为(具备相同输入和输出)的一簇函数说进行的普遍意义上的抽象, 从这个意义讲,委托是是面向对象的;从微软在c#2.0对委托的的输入和输出的拓展中,更可以看到委托OO的思想。
委托(delegate)和接口(Interface)的关系:
本质上讲,.net delegate就是一个数据类型(A delegate is a type),它具备继承机制,delegate本身继承自MulticastDelegate,重载了Invoke()函数。这样理解的话,delegate就更有OOP的思想。
MSDN中,将class, delegate,interface并列为.net中的三大类型(type),只是delegate比interface粒度更细。微软在相关文档中指出,能用delegate完成的,都能用interface代替