先寫一個最簡單的策略模式的例子
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的方法,只是可執行這些操作的對象增加了而已)。這種情況下用策略模式就會變得特別費勁,在需繼續寬展對象的時候就會是代碼變得很亂。
所以總結一下兩種模式各有好處,當抽象類中方法單一子類是去寬展功能的時候就用策略模式,當抽象類中的方法是在描述一個對象的行爲特徵,子類只是去擴展具體對象的時候還是用簡單工廠模式比較好啊