先写一个最简单的策略模式的例子
abstract class Calculate
{
public abstract void Operate();
}
class Add:Calculate
{
public override void Operate()
{
Debug.WriteLine("i can add");
}
}
class Sub:Calculate
{
public override void Operate()
{
Debug.WriteLine("i can sub");
}
}
class Context
{
Calculate cal;
public Context(Calculate cal)
{
this.cal = cal;
}
public void Operate()
{
this.cal.Operate();
}
}
class Client
{
public static void main()
{
Context context = new Context(new Add());
context.Operate();
}
}
上面的Context类就是一个策略类,他的作用就是把不同的功能类,通过构造函数的方式传给策略类,统一在策略类里进行操作。
在客户端调用的时候,只需调用策略类里面的方法就能行,不同方法的调用在实例化策略类的时候来体现差异化,这样的作用是表面是一直调用的Operate()方法,客户端看不到算法层。
写到这里,我开始思考之前的简单工厂模式也能有这个作用啊,而且在工厂类里面还能通过判断来具体进行实例化,应该比这个策略类还好用啊,那这个策略类岂不是没啥价值了,找了半天终于找到了他们之间的区别:差异就是工厂类跟策略类的不同,工厂是负责创建对象的,不负责调用对象的具体方法,而策略类创建对象的同时也调用了对象的方法。
策略类:
class Context
{
Calculate cal;
public Context(Calculate cal)
{
this.cal = cal;
}
public void Operate()
{
this.cal.Operate();
}
}
工厂类:
class Factory
{
public AnimalFactory CreateFactory
{
//此处略去switch的判断部分
return new Cat();
}
}
这就导致在客户端调用的时候,策略模式用策略类的实例能直接使用方法,而简单工厂模式得把工厂创建的对象赋给一个抽象的功能类,然后用这个功能类去调用相应的方法,这样就简化的调用过程。
但是这回你又会问了,那这么说策略模式比工厂模式好啊,那工厂模式是不是又没啥价着了,既然有好的何必用这个不好的呢。现在再来看一下两个具体的区别吧。
这个策略模式的功能类,就是Calculate这个分支,好比咱们前面讲的简单工厂模式中的面向接口的模式,或者说是面向功能、方法的模式。里面只有一个单一的方法是靠子类来实现并丰富这个方法的,虽然经过子类的实现功能扩展了,但是这个方法的名称不变,这样在策略类里面调用的时候才会变得非常简单。
如果是简单工厂模式中的对象化的编程,比如Animal中的Run跟Jump方法,它的子类是不同的动物,Dog,Cat,这些子类并不是为了拓展父类的功能,而是基于父类的方法,来做具体的适用于自己的实现(希望这一点好好理解,我想了好久才总结出之间的区别,第一种经过子类的扩展,可以本来只是简单操作的类变得有Add,Sub,Mul等等功能呢。而后者经过子类的扩展该整体还是只有Jump跟Run的方法,只是可执行这些操作的对象增加了而已)。这种情况下用策略模式就会变得特别费劲,在需继续宽展对象的时候就会是代码变得很乱。
所以总结一下两种模式各有好处,当抽象类中方法单一子类是去宽展功能的时候就用策略模式,当抽象类中的方法是在描述一个对象的行为特征,子类只是去扩展具体对象的时候还是用简单工厂模式比较好啊