前言 一、原型模式的作用? 1、基本就是你需要從A的實例得到一份與A內容相同,但是又互不干擾的實例的話,就需要使用原型模式。 2、用原型實例指定創建對象的種類,並且通過拷貝這些原型創建新的對象。這個其實和C++的拷貝構造函數的作用是相似的(但不相同),實際上就是動態抽取 當前對象 運行時 的 狀態。 3、當然有的時候,如果我們並不需要基於現有的對象複製新的對象,或者我們需要的就是一個乾淨的空對象,那麼我的首先還是工廠模式或者抽象工廠模式。
二、為什麼需要原型模式? 1、為什麼不用new直接新建對象,而要用原型模式? 首先,用new新建對像不能獲取當前對象運行時的狀態,其次就算new了新對象,在將當前對象的值複製給新對象,效率也不如原型模式高。 2、為什麼不直接使用拷貝構造函數,而要使用原型模式? 原型模式與拷貝構造函數是不同的概念,拷貝構造函數涉及的類是已知的,原型模式涉及的類可以是未知的(基類的拷貝構造函數只能複制得到基類的對象)。 原型模式生成的新對象可能是一個派生類。拷貝構造函數生成的新對像只能是類本身。原型模式是描述了一個通用方法(或概念),它不管是如何實現的,而拷貝構造則是描述了一個具體實現方法。
UML
程式碼 淺拷貝 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 class Program { static void Main (string [] args ) { ConcreteCar concreteCar = new ConcreteCar("Benz" , 100 , 4 ); ConcreteCar concreteCar1 = (ConcreteCar)concreteCar.Clone(); concreteCar1.Model = "Toyoto" ; concreteCar.Show(); concreteCar1.Show(); } } class ConcreteCar : ICloneable { private string model; private int speend; private int wheel; public ConcreteCar (string _model, int _speend, int _wheel ) { model = _model; speend = _speend; wheel = _wheel; } public string Model { get { return model; } set { model = value ; } } public void Show () { Console.WriteLine($"車子品牌:{model} ,速度:{speend} KM,輪子:{wheel} " ); } public object Clone () { return this .MemberwiseClone(); } }
輸出結果
深拷貝 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 class Program { static void Main (string [] args ) { ConcreteWheel concreteWheel = new ConcreteWheel(4 , "380" ); ConcreteCar concreteCar = new ConcreteCar("Benz" , 100 , concreteWheel); ConcreteCar shallowconcreteCar = (ConcreteCar)concreteCar.Clone(); ConcreteCar deepconcreteCar = (ConcreteCar)concreteCar.DeepClone(); Console.WriteLine("=====未更改的原形======" ); concreteCar.Show(); Console.WriteLine("=====淺拷貝更改======" ); shallowconcreteCar.ConcreteWheel.Wheel = 10 ; shallowconcreteCar.Show(); Console.WriteLine("=====被更改的原形======" ); concreteCar.Show(); Console.WriteLine("=====深拷貝更改======" ); deepconcreteCar.ConcreteWheel.Wheel = 200 ; deepconcreteCar.Show(); Console.WriteLine("====未被改的原形======" ); concreteCar.Show(); } } class ConcreteCar : ICloneable { private string model; private int speend; private ConcreteWheel concreteWheel; public ConcreteCar (string _model, int _speend, ConcreteWheel _concreteWheel ) { model = _model; speend = _speend; concreteWheel = _concreteWheel; } public string Model { get { return model; } set { model = value ; } } public void Show () { Console.WriteLine($"車子品牌:{model} ,車速:{speend} ,車子輪子{concreteWheel.Show()} " ); } public ConcreteWheel ConcreteWheel { get { return concreteWheel;} set { concreteWheel = value ; } } public object DeepClone () { ConcreteCar concreteCar = new ConcreteCar(model, speend, concreteWheel.newClone()); return concreteCar; } public object Clone () { return this .MemberwiseClone(); } } class ConcreteWheel : ICloneable { private int wheel; private string motor; public ConcreteWheel (int _wheel, string _motor ) { wheel = _wheel; motor = _motor; } public string Show () { return $"車子輪數:{wheel} ,車子馬達:{motor} " ; } public int Wheel { get { return wheel; } set { wheel = value ; } } public object Clone () { return this .MemberwiseClone(); } public ConcreteWheel newClone () { return new ConcreteWheel(wheel, motor); } }
輸出結果
結語 優缺點 優點: 原型模式向客戶隱藏了建立新例項的複雜性 原型模式允許動態增加或較少產品類。 原型模式簡化了例項的建立結構,工廠方法模式需要有一個與產品類等級結構相同的等級結構,而原型模式不需要這樣。 產品類不需要事先確定產品的等級結構,因為原型模式適用於任何的等級結構
缺點: 每個類必須配備一個克隆方法。 配備克隆方法需要對類的功能進行通盤考慮,這對於全新的類不是很難,但對於已有的類不一定很容易,特別當一個類引用不支援序列化的間接物件,或者引用含有迴圈結構的時候。