C#設計模式 之 原型模式
別名:克隆模式、Prototype
一,意圖
用原型實例指定創建對象的種類,并且通過拷貝這些原型創建新的對象。
二,動機
在程序設計中,經常面臨著“某些結構復雜的對象”的創建工作;由于需求的變化,這些對象經常面臨著劇烈的變化,但是它們卻擁有比較穩定一致的接口。
問題來了:
如何創建易變類的實體對象?
解決方案:
采用“原型克隆”的方法來做,它是的我們可以非常靈活地動態創建“擁有某些穩定接口”的新對象 – 所需工作僅僅是注冊一個新類的對象(原型),然后在任何需要的地方不斷的Clone
要點:
原型設計模式用于隔離類對象的使用者和具體類型(易變類)之間的耦合關系,它要求這些易變類擁有穩定的接口。
三,結構
原型 (Prototype) 接口將對克隆方法進行聲明。 通常情況下, 其中只會有一個名為 clone克隆的方法。
具體原型 (Concrete Prototype) 類將實現克隆方法。 除了將原始對象的數據復制到克隆體中之外, 該方法有時還需處理克隆過程中的極端情況, 例如克隆關聯對象和梳理遞歸依賴等等。
客戶端 (Client) 可以復制實現了原型接口的任何對象。
四,優缺點
優點:
可以克隆對象, 而無需與它們所屬的具體類相耦合。
可以克隆預生成原型, 避免反復運行初始化代碼。
可以更方便地生成復雜對象。
可以用繼承以外的方式來處理復雜對象的不同配置。
缺點:
克隆包含循環引用的復雜對象可能會非常麻煩。
五,應用場景
適用性:
當一個系統應該獨立于它的產品創建,構成和表示時,要使用原型模式;以及當要實例化的類是在運行時刻指定時,
為了創建一個與產品類層次平行的工廠類層次時
當一個類的實例只能有幾種不同狀態的組合中的一種時。建立相應數目的原型并克隆他們可能比每次用合適的狀態手工實例化該類更方便。
六,代碼實現
實現方式:
創建一個原型管理器:原型管理器是一個關聯存儲器,它返回一個與給定關鍵字匹配的原型。
實現克隆操作:原型設計模式最困難的部分在于正確實現Clone操作。C#語言為我們提供this.MemberwiseClone();來實現淺拷貝。而深拷貝我們可以通過序列化去實現。
初始化克隆對象:在不同的情況下,客戶程序使用需要不同的初始值,所以一些原型可能要多個初始化參數。
拓展:什么是“淺拷貝和深拷貝”?
淺拷貝:克隆對象和原對象共享引用類型的變量 (引用類型同指向一個內存)
深拷貝:克隆一個對象時依次克隆它的實例變量 (所有數據間沒有任何關系)
可以簡單理解為,淺拷貝是List
示例代碼:
class Program { static void Main(string[] args) { Person p1 = new Person(); p1.Age = 22; p1.Name = "Czhenya"; p1.IdInfo = new IdInfo(111); // 對p1執行一個淺拷貝,并將其賦值給p2。 Person p2 = p1.ShallowCopy(); // 對p1做一個深度拷貝,并把它賦值給p3。 Person p3 = p1.DeepCopy(); Console.WriteLine("----- p1, p2, p3的原始值: -----"); Console.WriteLine("--- 原數據 P1 :"); DisplayValues(p1); Console.WriteLine("--- 淺拷貝 P2 :"); DisplayValues(p2); Console.WriteLine("--- 深拷貝 P3 :"); DisplayValues(p3); // 更改p1屬性的值并顯示p1的值 p1.Age = 33; p1.Name = "Czy"; p1.IdInfo.IdNumber = 222; Console.WriteLine(); Console.WriteLine("----- 對原數據p1 進行修改后 p1、p2、p3的值: -----") Console.WriteLine("+++ 原數據 P1 :"); DisplayValues(p1); Console.WriteLine("+++ 淺拷貝 P2 :"); DisplayValues(p2); Console.WriteLine("+++ 深拷貝 P3 :"); DisplayValues(p3); Console.ReadKey(); } static void DisplayValues(Person p) { Console.WriteLine("姓名: {0:s}, 年齡: {1:d}, ID: {2:d}", p.Name, p.Age } } ///
測試結果:
設計模式系列博文示例代碼工程:鏈接
C#
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。