在軟件系統中,當建立一個類的實例的過程很昂貴或很複雜,而且咱們須要建立多個這樣類的實例時,若是咱們用new操做符去建立這樣的類實例,這未免會增長建立類的複雜度和耗費更多的內存空間,由於這樣在內存中分配了多個同樣的類實例對象,而後若是採用工廠模式來建立這樣的系統的話,隨着產品類的不斷增長,致使子類的數量不斷增多,反而增長了系統複雜程度,因此在這裏使用工廠模式來封裝類建立過程並不合適,然而原型模式能夠很好地解決這個問題,由於每一個類實例都是相同的,當咱們須要多個相同的類實例時,不必每次都使用new運算符去建立相同的類實例對象,此時咱們通常思路就是想——只建立一個類實例對象,若是後面須要更多這樣的實例,能夠經過對原來對象拷貝一份來完成建立,這樣在內存中不須要建立多個相同的類實例,從而減小內存的消耗和達到類實例的複用。 然而這個思路正是原型模式的實現方式。下面就具體介紹下設計模式中的原型設計模式。c#
在現實生活中,也有不少原型設計模式的例子,例如,細胞分裂的過程,一個細胞的有絲分裂產生兩個相同的細胞;還有西遊記中孫悟空變出後孫的本領和火影忍者中鳴人的隱分身忍術等。下面就以孫悟空爲例子來演示下原型模式的實現。具體的實現代碼以下:設計模式
///火影忍者中鳴人的影分身和孫悟空的的變都是原型模式 class Client { static void Main(string[] args) { // 孫悟空 原型 MonkeyKingPrototype prototypeMonkeyKing = new ConcretePrototype("MonkeyKing"); // 變一個 MonkeyKingPrototype cloneMonkeyKing = prototypeMonkeyKing.Clone() as ConcretePrototype; Console.WriteLine("Cloned1:\t"+cloneMonkeyKing.Id); // 變兩個 MonkeyKingPrototype cloneMonkeyKing2 = prototypeMonkeyKing.Clone() as ConcretePrototype; Console.WriteLine("Cloned2:\t" + cloneMonkeyKing2.Id); Console.ReadLine(); } } /// <summary> /// 孫悟空原型 /// </summary> public abstract class MonkeyKingPrototype { public string Id { get; set; } public MonkeyKingPrototype(string id) { this.Id = id; } // 克隆方法,即孫大聖說「變」 public abstract MonkeyKingPrototype Clone(); } /// <summary> /// 建立具體原型 /// </summary> public class ConcretePrototype : MonkeyKingPrototype { public ConcretePrototype(string id) : base(id) { } /// <summary> /// 淺拷貝 /// </summary> /// <returns></returns> public override MonkeyKingPrototype Clone() { // 調用MemberwiseClone方法實現的是淺拷貝,另外還有深拷貝 return (MonkeyKingPrototype)this.MemberwiseClone(); } }
上面原型模式的運行結果爲(從運行結果能夠看出,建立的兩個拷貝對象的ID屬性都是與原型對象ID屬性同樣的):ide
上面代碼實現的淺拷貝的方式,淺拷貝是指當對象的字段值被拷貝時,字段引用的對象不會被拷貝。例如,若是一個對象有一個指向字符串的字段,而且咱們對該對象作了一個淺拷貝,那麼這兩個對象將引用同一個字符串,而深拷貝是對對象實例中字段引用的對象也進行拷貝,若是一個對象有一個指向字符串的字段,而且咱們對該對象進行了深拷貝的話,那麼咱們將建立一個對象和一個新的字符串,新的對象將引用新的字符串。也就是說,執行深拷貝建立的新對象和原來對象不會共享任何東西,改變一個對象對另一個對象沒有任何影響,而執行淺拷貝建立的新對象與原來對象共享成員,改變一個對象,另一個對象的成員也會改變。工具
介紹完原型模式的實現代碼以後,下面看下原型模式的類圖,經過類圖來理清原型模式實現中類之間的關係。具體類圖以下:this
原型模式的優勢有:spa
原型模式向客戶隱藏了建立新實例的複雜性prototype
原型模式容許動態增長或較少產品類。設計
原型模式簡化了實例的建立結構,工廠方法模式須要有一個與產品類等級結構相同的等級結構,而原型模式不須要這樣。對象
產品類不須要事先肯定產品的等級結構,由於原型模式適用於任何的等級結構繼承
原型模式的缺點有:
每一個類必須配備一個克隆方法
配備克隆方法須要對類的功能進行通盤考慮,這對於全新的類不是很難,但對於已有的類不必定很容易,特別當一個類引用不支持串行化的間接對象,或者引用含有循環結構的時候。
在.NET中能夠很容易地經過實現ICloneable接口(這個接口就是原型,提供克隆方法,至關於與上面代碼中MonkeyKingPrototype抽象類)中Clone()方法來實現原型模式,若是咱們想咱們自定義的類具備克隆的功能,首先定義類繼承與ICloneable接口並實現Clone方法。在.NET中實現了原型模式的類以下圖所示(圖中只截取了部分,能夠用Reflector反編譯工具進行查看):
到這裏關於原型模式的介紹就結束了,原型模式用一個原型對象來指明所要建立的對象類型,而後用複製這個原型對象的方法來建立出更多的同類型對象,它與工廠方法模式的實現很是類似,其中原型模式中的Clone方法就相似工廠方法模式中的工廠方法,只是工廠方法模式的工廠方法是經過new運算符從新建立一個新的對象(至關於原型模式的深拷貝實現),而原型模式是經過調用MemberwiseClone方法來對原來對象進行拷貝,也就是複製,同時在原型模式優勢中也介紹了與工廠方法的區別(第三點)。