原型模式(Prototype)
阿新 • • 發佈:2018-01-25
on() 原型對象 orm obj 如何 取數據 .com 遞歸 從數據
模式定義
原型模式是一種創建型設計模式,Prototype模式允許一個對象再創建另外一個可定制的對象,根本無需知道任何如何創建的細節,工作原理是:通過將一個原型對象傳給那個要發動創建的對象,這個要發動創建的對象通過請求原型對象拷貝它們自己來實施創建。
UML類圖
- 抽象原型
- 具體原型
客戶端調用
代碼結構
MemberwiseClone()
方法是Object
對象的淺復制的方法。public static class Client { public static void Run() { ConcretePrototype p = new ConcretePrototype("I"); ConcretePrototype c = (ConcretePrototype)p.Clone(); if(p != c) { Console.WriteLine("The Copy Object is not same."); } Console.WriteLine(c.Id); } } public abstract class Prototype { private string _id; public Prototype(string id) { this._id = id; } public string Id { get { return _id; } } public abstract Prototype Clone(); } public class ConcretePrototype : Prototype { public ConcretePrototype(string id) : base(id) { } public override Prototype Clone() { return (Prototype)this.MemberwiseClone(); } }
C#代碼優化
其實沒必要定義抽象原型對象,如那個類需要具有復制的功能,直接繼承
ICloneable
接口就可以了public class ConcretePrototype : ICloneable { private string _id; public string Id { get { return _id; } } public ConcretePrototype(string id) { this._id = id; } public object Clone() { return this.MemberwiseClone(); } }
深度復制
以上談論的類中不包含引用類型成員(string
類型除外,因每次操作其實新建一個對象,可當作值類型處理)。如果包含引用成員,以上為淺復制(即引用成員被對象和復制對象公用)。當然這是不希望的兩種解決辦法。
- 通過遞歸反射,發放存在引用成員(
string
除外)新建對象(實現復雜) 通過序列化與反序列化(實現簡單)
通過序列化深度復制對象,假設一人對象有名稱和住址,住址為引用類型。public static class PrototypeClient { public static void Run() { Person p1 = new Person() { Name = "LoveTomato", Address = new Address("China", "BeiJing", "Haidian") }; Person p2 = p1.Clone() as Person; p2.Address.Area = "Chaoyang"; Console.Write("\nName:{0},Address{1}", p1.Name, p1.Address.ToString()); Console.Write("\nName:{0},Address{1}", p2.Name, p2.Address.ToString()); } } [Serializable] public class Person : ICloneable { public string Name { get; set; } public Address Address { get; set; } public object Clone() { BinaryFormatter bf = new BinaryFormatter(); MemoryStream ms = new MemoryStream(); bf.Serialize(ms, this); ms.Position = 0; return (bf.Deserialize(ms)); } } [Serializable] public class Address { public string Country { get; set; } public string City { get; set; } public string Area { get; set; } public Address(string country, string city, string area) { this.Country = country; this.City = city; this.Area = area; } public override string ToString() { return string.Format("Country:{0},City:{1},Area:{2}", this.Country, this.City, this.Area); } }
情景模式
在新建一個對象花費代價比較大時(需要從數據庫或遠程獲取數據等),可以使用原型法創建對象。
在對數據庫中數據修改做日誌時,要求記錄修改前值與修改後值。因為項目通過ORM操作數據庫,則可先根據原型創建一對象作為修改前值(如果從數據庫中查找兩次比較耗時)。
原型模式(Prototype)