Prototype模式的動機
在軟件系統中,經常面臨著"某些結構復雜的對象"的創建工作;由於需求的變化,這些對象經常面臨著劇烈的變化,但是它們卻擁有比較穩定一致的接口。
如何應對這種變化?如何向"客戶程序(使用這些對象的程序)"隔離出"這些易變對象" ,從而使得"依賴這些易變對象的客戶程序"不隨著需求改變而改變?
Prototype模式的意圖
使用原型實例指定創建對象的種類,然後通過拷貝這些原型來創建新的對象。
下面看看代碼
首先我們有三個穩定的抽象基類
public abstract class NormalActor
...{
public abstract NormalActor Clone();
}
public abstract class FlyActor
...{
public abstract FlyActor Clone();
}
public abstract class WaterActor
...{
public abstract WaterActor Clone();
}
這三個抽象基類是比較穩定的類
現在每個抽象基類裡都有兩個派生類,並且實現了抽象方法Clone。
public class NormalActorA : NormalActor
...{
public override NormalActor Clone()
...{
return (NormalActor)this.MemberwiseClone();
}
}
public class NormalActorB : NormalActor
...{
public override NormalActor Clone()
...{
return (NormalActor)this.MemberwiseClone();
}
}
public class FlyActorA : FlyActor
...{
public override FlyActor Clone()
...{
return (FlyActor)this.MemberwiseClone();
}
}
public class FlyAcotrB : FlyActor
...{
public override FlyActor Clone()
...{
return (WaterActor)this.MemberwiseClone();
}
}
那麼這些派生類可以說不是很穩定的,他們可以被擴展。
那麼現在有一個GameSystem類,這個類有一個方法
public class GameSystem
...{
public static void Run(NormalActor normalActor,
FlyActor flyActor,
WaterActor waterActor)
...{
NormalActor normalActor1 = normalActor.Clone();
NormalActor normalActor2 = normalActor.Clone();
NormalActor normalActor3 = normalActor.Clone();
NormalActor normalActor4 = normalActor.Clone();
FlyActor flyActor1 = flyActor.Clone();
FlyActor flyActor2 = flyActor.Clone();
WaterActor waterActor1 = waterActor.Clone();
WaterActor waterActor2 = waterActor.Clone();
}
注意在這個方法裡的參數normalActor等對象可以置為字段,這個是不重要的。重要的是我們根據給定的三個類型的實例,通過Clone方法,來創建相應的拷貝對象。
那麼當我們調用Run方法的時候
static void Main(string[] args)
...{
GameSystem.Run(new NormalActorA(),
new FlyActorA(),
new WaterAcotrA());
}
我們通過傳入的對象的類型,使Run方法裡的創建的對象與傳入的對象一致。但是我們使用MemberwiseClone方法的時候要注意,這是一個淺拷貝對象的方法,對於一個字段都為值類型的類是適用的,但是,如果有引用類型,這樣會導致同一塊內存被兩個引用指向。我們可以在Clone方法裡對此進行處理,講對象字段新new出來,並且逐項賦值。也可以實現序列化接口,讓類序列化,那麼拷貝的時候是新生成的對象。
Prototype模式的幾個要點
- Prototype模式同樣用於隔離類對象的使用者和具體類型(易變類)之間的耦合關系,它同樣要求這些"易變類"擁有"穩定的接口"。
- Prototype模式對於"如何創建易變類的實體對象"采用"原型克隆"的方法來做,它使得我們可以非常靈活地動態創建"擁有某些穩定接口"的新對象--所需工作僅僅是注冊一個新類的對象(即原型),然後在任何需要的地方不斷地Clone。
- Prototype模式中的Clone方法可以利用.Net中的Object類的MemberwiseClone()方法或者序列化來實現深拷貝。
有關創建性模式的討論
- Singleton模式解決的是實體對象個數的問題。除了Singleton之外,其他創建型模式解決的都是new所帶來的耦合關系。
- Factory Method, Abstract Factory, Builder都需要一個額外的工廠類來負責實例化"易變對象",而Prototype則是通過原型(一個特殊的工廠類)來克隆"易變對象"。
- 如果遇到"易變類",起初的設計通常從FactoryMethod開始,當遇到更多的復雜變化時,再考慮重構為其他三種工廠模式( Abstract Factory,Builder , Prototype )。