引言:
原型模式是什么?它是在什么場景下被提出的呢?本章節,我們將詳細了解下原型模式,
在軟體系統中,當創建一個類的實體程序過于昂貴或復雜,并且我們需要創建多個這樣類的實體時,如果我們通過new來創建類實體,這就會增加創建類的復雜度和創建程序與客戶代碼復雜的耦合度,如果采用工廠模式來創建這樣的實體物件的話,隨著產品類的不斷增加,導致子類的數量不斷增多,也導致了相應工廠類的增加,維護的代碼維度增加了,因為有產品和工廠兩個維度了,反而增加了系統復雜程度,所以在這里使用工廠模式來封裝類創建程序并不合適,由于每個類實體都是相同的(型別相同),但是每個實體的狀態引數會有不同,如果狀態數值也相同就沒意義了,有一個這樣的物件就可以了,當我們需要多個相同的類實體時,可以通過對原來物件拷貝一份來完成創建,這個思路正是原型模式的實作方式,
定義:
原型模式就是通過給出一個原型物件來指明所要創建的物件型別,然后用復制這個物件的方法來創建更多的同型別物件,
原型模式的兩種型別:
object類的clone方法只會拷貝物件中基本的資料型別,對于陣列、容器物件、參考物件等都不會拷貝,這就是淺拷貝,如果要實作深拷貝,必須將原型模式中的陣列、容器物件、參考物件等另行拷貝,

1 internal class Program 2 { 3 private static void Main(string[] args) 4 { 5 SunWukong sunwukong = new SunWukong() 6 { 7 Id = 1, 8 Name = "孫悟空", 9 Weapon = new Weapon()10 {11 Name = "如意金箍棒"12 }13 };14 SunWukong xingzhesun = (SunWukong)sunwukong.Clone();15 Console.WriteLine($"{sunwukong.Id}-{sunwukong.Name}-{sunwukong.Weapon.Name}");16 Console.WriteLine($"{xingzhesun.Id}-{xingzhesun.Name}-{xingzhesun.Weapon.Name}");17 Console.WriteLine("===============================");18 19 // 驗證克隆后屬性之間是否共享20 xingzhesun.Id = 2;21 xingzhesun.Name = "行者孫";22 xingzhesun.Weapon.Name = "釘耙";23 Console.WriteLine($"{xingzhesun.Id}-{xingzhesun.Name}-{xingzhesun.Weapon.Name}");24 Console.WriteLine($"{sunwukong.Id}-{sunwukong.Name}-{sunwukong.Weapon.Name}");25 // 從結果可以看出,對于基本型別屬性,克隆之后不共享,而對于物件來說是共享的,這就是淺拷貝26 Console.WriteLine("===============================");27 Console.WriteLine($"孫悟空的武器{sunwukong.Weapon.GetHashCode()},行者孫的武器{sunwukong.Weapon.GetHashCode()}");28 // 列印hashcode值可以看出,克隆后的實體與原型的Weapon指向同一個地址29 }30 }31 32 internal class SunWukong : ICloneable33 {34 public int Id { get; set; }35 public string Name { get; set; }36 public Weapon Weapon { get; set; }37 38 public object Clone()39 {40 return this.MemberwiseClone();41 }42 }43 44 internal class Weapon45 {46 public string Name { get; set; }47 }view code
.net中提供了原型,即System命名空間下的介面ICloneable,只要實作該介面的Clone方法就可以之間原型拷貝,上述代碼中遺留了一個問題,如何實作深拷貝問題,

1 internal class Program 2 { 3 private static void Main(string[] args) 4 { 5 SunWukong sunwukong = new SunWukong() 6 { 7 Id = 1, 8 Name = "孫悟空", 9 Weapon = new Weapon()10 {11 Name = "如意金箍棒"12 }13 };14 SunWukong xingzhesun = (SunWukong)sunwukong.Clone();15 // 參考型別再進行拷貝16 xingzhesun.Weapon = (Weapon)xingzhesun.Weapon.Clone();17 Console.WriteLine($"{sunwukong.Id}-{sunwukong.Name}-{sunwukong.Weapon.Name}");18 Console.WriteLine($"{xingzhesun.Id}-{xingzhesun.Name}-{xingzhesun.Weapon.Name}");19 Console.WriteLine("===============================");20 xingzhesun.Id = 2;21 xingzhesun.Name = "行者孫";22 xingzhesun.Weapon.Name = "釘耙";23 Console.WriteLine($"{xingzhesun.Id}-{xingzhesun.Name}-{xingzhesun.Weapon.Name}");24 Console.WriteLine($"{sunwukong.Id}-{sunwukong.Name}-{sunwukong.Weapon.Name}");25 Console.WriteLine("===============================");26 Console.WriteLine($"孫悟空的武器{sunwukong.Weapon.GetHashCode()},行者孫的武器{xingzhesun.Weapon.GetHashCode()}");27 }28 }29 30 internal class SunWukong : ICloneable31 {32 public int Id { get; set; }33 public string Name { get; set; }34 public Weapon Weapon { get; set; }35 36 public object Clone()37 {38 return this.MemberwiseClone();39 }40 }41 42 internal class Weapon : ICloneable43 {44 public string Name { get; set; }45 46 public object Clone()47 {48 return this.MemberwiseClone();49 }50 }view code
深拷貝:
1、復制物件的基本資料型別的成員變數值,
2、為所有參考型別的成員變數申請存盤空間,并復制每個參考資料型別成員變數所參考的物件,直到該物件可達的所有物件,也就是說,物件進行深拷貝要對整個物件進行拷貝,
3、深拷貝實作方式1:重寫clone方法,
4、深拷貝實作方式2:通過物件序列化,

1 //物件深拷貝 2 public static T Copy<T>(T oldObject) where T : class,new() 3 { 4 T newOrder = new T(); 5 MemoryStream stream = new MemoryStream(); 6 BinaryFormatter bf = new BinaryFormatter(); 7 bf.Serialize(stream, oldObject); 8 stream.Position = 0; 9 newOrder = (bf.Deserialize(stream) as T);10 return newOrder;11 }view code
原型模式的注意事項和細節:
1、創建新的物件比較復雜時,可以利用原型模式簡化物件的創建程序,同時也能夠提高效率,
2、不用重新初始化物件,而是動態地獲取物件運行時的狀態,
3、如果原始物件發生變化(增加或減少屬性),其它克隆物件也會發生相應的變化,無需修改代碼,
4、在實作深克隆的時候可能需要比較復雜的代碼,
5、使用原型模式復制不會呼叫類的構造方法,因為物件的復制是通過呼叫clone方法完成的,它直接在記憶體種復制資料,因此不會呼叫到類的構造方法,不但構造方法中的代碼不會執行,甚至連訪問權限都對原型模式無效,單例模式中,我們通過私有化建構式來實作單例模式,但clone方法直接無視構造方法的權限,所以,單例模式與原型模式是沖突的,
原型模式的優點:
1、原型模式向客戶隱藏了創建新實體的復雜性,
2、原型模式允許動態增加或較少產品類,
3、原型模式簡化了實體的創建結構,工廠方法模式需要有一個與產品類等級結構相同的等級結構,而原型模式不需要這樣,
4、產品類不需要事先確定產品的等級結構,因為原型模式適用于任何的等級結構,
缺點:
1、需要為每一個類配備一個克隆方法,這對全新的類來說不是很難,但對已有的類進行改造時,需要修改原始碼,即違反了OCP原則,
參考:https://www.cnblogs.com/zhili/p/PrototypePattern.html
https://yq.aliyun.com/articles/485574
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/46465.html
標籤:設計模式
下一篇:設計模式-創建型-建造者模式

