浅谈原型模式
? ? ? 近期菜鳥D在看《大話設計模式》,看到原型模式,有一點自己的想法,所以就記下來。
? ? ? 老規矩,解釋定義:
? ? ? 用原型實例指定創建對象的種類,并且通過拷貝這些原型創建新的對象。
? ? ? Prototype原型模式是一種創建型設計模式,Prototype模式允許一個對象再創建另外一個可定制的對象,根本無需知道任何如何創建的細節,工作原理是:通過將一個原型對象傳給那個要發動創建的對象,這個要發動創建的對象通過請求原型對象拷貝它們自己來實施創建。 ? ? ? ? ? ? ? ? ? ? ? ? ?——來自百度?
? ? ? 由于感覺光看書不動手實踐一下有點不靠譜,就按著自己的理解寫了段代碼,情景參照《大話設計模式》第9章,簡歷的復制。
代碼如下:
//原型類實現接口ICloneable public class Prototype : ICloneable{public string ID { get; private set; }public string Exp { get; set; }private Company company = new Company();public Prototype(string id){ID = id;}public void SetExp(string exp){Exp = exp;}#region 引用類型的拷貝//SetCompany是淺拷貝public void SetCompany(string address){company.Address = address;}//SetCompany1是深拷貝public void SetCompany1(string address){Company c = (Company)company.Clone();c.Address = address;company = c;} #endregionpublic void Show(){Console.WriteLine("id:{0} exp:{1} company:{2}", ID, Exp, company.Address);}public object Clone(){return MemberwiseClone();}}//公司類,也可以拷貝 public class Company : ICloneable{private string address;public string Address{get { return address; }set { address = value; }}public object Clone(){return MemberwiseClone();}}//客戶端Prototype p1 = new Prototype("1");p1.SetExp("半年經驗");p1.SetCompany("世紀財富中心");//p1.Show();Prototype p2 = (Prototype)p1.Clone();p2.SetExp("1年經驗");p2.SetCompany("帝國大廈");//p2.Show();Prototype p3 = (Prototype)p1.Clone();p3.SetCompany1("華爾街");//p3.Show(); p1.Show();p2.Show();p3.Show();//執行客戶端的注釋代碼會發現有不同的結果,所以代碼的執行邏輯也必須要理清? ? ?運行結果:
結果1:
結果2:
結果3:
?
? ? ?代碼的分析:
? ? ? 在客戶端代碼中p2沒有調用構造方法,而是調用p1的clone方法,所以內存中沒有產生新的對象,p2引用p1的對象。當p2修改company時,p1的company也發生改變。p3同樣調用p1的clone方法,但是p3使用SetCompany1來設置company,在SetCompany1的內部并不是直接給company賦值,而是重新克隆company,賦值給company字段,所以p3修改并沒有將p1,p2的修改覆蓋。出現運行結果1。
? ? ? 在調整代碼的執行順序之后,可以看到p2的修改似乎沒有影響p1(如結果2),但其實p2的修改已經影響了p1,只是p1的輸出在前面執行。于是在結果3中可以看到修改。
? ? ? 從以上代碼及其結果,不難看出是深拷貝和淺拷貝以及代碼的執行順序的影響。
? ? ? 原源碼(大話設計模式P88)是通過在私有的構造函數中克隆WorkExperience,并將克隆體賦值給自己,從而產生區別。大話設計模式P87有深拷貝,淺拷貝的介紹。
? ? ? 結合C++的知識,淺拷貝是將新對象的指針指向原有的對象,不再復制原有對象。深拷貝是將原有對象復制一個份,讓新對象的指針指向復制后的地址。(如下附圖)
? ? ? 結合C#的知識,淺拷貝是新對象引用原有對象,內存中沒有產生新的對象。深拷貝是在內存中開辟空間創建對象,并將原有對象的值復制,新對象引用內存中新產生的對象,只是與原有對象的值一致,從內存地址上看和原有對象沒有關系。? ? ?
? ? ? 應用的場景:
? ? ? 從代碼角度來說,避免創建對象時的初始化過程(如果這個過程占用的時間和資源都非常多),或者是希望避免使用工廠方法來實現多態的時候,可以考慮原型模式。
從應用角度來說, 如果你創建的對象是多變化、多等級的產品,或者產品的創建過程非常耗時的時候(比如,有一定的計算量,或者對象創建時需要從網絡或數據庫中獲取一定的數據),或者想把產品的創建獨立出去,不想了解產品創建細節的時候可以考慮使用。
? ? ?注意事項:
? ? ?深拷貝和淺拷貝的使用場景,哪些是公有的允許修改的,哪些是不允許修改的。值類型和引用類型在深淺拷貝中的結果是不一樣的。
? ? ?拷貝原型并進行修改意味著原型需要公開更多的數據,對已有系統實現原型模式可能修改的代價比較大。
附圖:
部分內容摘自 ? http://www.cnblogs.com/promise-7/archive/2012/06/01/2530734.html
菜鳥D希望這篇文章對您有所幫助。
轉載于:https://www.cnblogs.com/cnDqf/p/4108266.html
總結
- 上一篇: 串的块链存储结构
- 下一篇: Java 螺纹第三版 第三章数据同步 读