本節介紹Util應用框架如何進行驗證. 概述 驗證是業務健壯性的基礎. .Net 提供了一套稱為 DataAnnotations 數據註解的方法,可以對屬性進行一些基本驗證,比如必填項驗證,長度驗證等. Util應用框架使用標準的數據註解作為基礎驗證,並對自定義驗證進行擴展. 基礎用法 引用Nuge ...
基礎介紹:
具體可分為2個角色:
Prototype(原型類):聲明一個Clone自身的介面;
ConcretePrototype(具體原型類):,實現一個Clone自身的操作。
在原型模式中,Prototype通常提供一個包含Clone方法的介面,具體的原型ConcretePrototype使用Clone方法完成對象的創建。
本質:通過拷貝這些原型對象創建新的對象。
根據其本質可以理解,原型本身就是通過一個自身的Clone方法來進行自我複製,從而產生新的對象。
比如,孫猴子吹猴毛變化多個克隆體時,就是用了原型模式,通過對自身的自我複製從而生產出N個分身。
所以從本質出發,想要實現這個功能,可以引出兩個概念:其一就是淺層複製,再則就是深層複製。
淺層複製:通過this.MemberWiseClone(),對實例的值類型進行拷貝(包含string類型),對引用類型只拷貝了引用。淺拷貝只對值類型成員進行複製,對於引用類型,只是複製了其引用,並不複製其對象。
深層複製:需要通過反射和序列化來實現。
應用場景:
對象在創建(new)時,消耗資源過多或繁瑣耗時。
本質就是在對象的構造函數中有耗時長或者占用系統資源多的情況,
使用原型模式進行複製對象時,可以省去這些耗時耗力的操作,直接獲得對象的具體實例。
最常見的使用場景之一就是對象歷史節點的保存,比如在對對象進行操作一次後,進行一次複製保存當前狀態(恢復到某一歷史狀態),可實現撤銷操作。
創建方式:
-
原型類----用來規範具體原型
1 /// <summary> 2 /// 原型類 3 /// </summary> 4 public abstract class Prototype 5 { 6 /// <summary> 7 /// 值類型 8 /// </summary> 9 public int Id { get; set; } 10 11 /// <summary> 12 /// 字元串 13 /// </summary> 14 public string strMessage { get; set; } 15 16 /// <summary> 17 /// 引用類型 18 /// </summary> 19 public Dictionary<int, string> keyValuePairs = new Dictionary<int, string>() { }; 20 21 /// <summary> 22 /// 構造函數 23 /// </summary> 24 /// <param name="id"></param> 25 public Prototype(int id) 26 { 27 this.Id = id; 28 } 29 30 /// <summary> 31 /// 複製函數 32 /// </summary> 33 /// <returns></returns> 34 public abstract Prototype Clone(); 35 }
View Code通過上述代碼可以看出,為了更好的展示原型類的特性,原型類中聲明瞭值類型和引用類型來展示各自的變化。
-
具體原型類
1 /// <summary> 2 /// 創建具體原型 3 /// </summary> 4 public class ConcretePrototype : Prototype 5 { 6 public ConcretePrototype(int id) 7 : base(id) 8 { } 9 10 /// <summary> 11 /// 淺拷貝 12 /// </summary> 13 /// <returns></returns> 14 public override Prototype Clone() 15 { 16 // 調用MemberwiseClone方法實現的是淺拷貝,另外還有深拷貝 17 return (Prototype)this.MemberwiseClone(); 18 } 19 }
View Code通過MemberwiseClone方法實現淺拷貝,即複製值類型屬性生成新的,而引用類型的屬性只複製其引用,並沒有生成新的。
-
客戶端調用
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 ConcretePrototype concretePrototype = new ConcretePrototype(1); 6 concretePrototype.strMessage = "AAAAAAAAA"; 7 concretePrototype.keyValuePairs.Add(1, "A"); 8 concretePrototype.keyValuePairs.Add(2, "B"); 9 Console.WriteLine("id:{0}", concretePrototype.Id); 10 Console.WriteLine("strMessage:{0}", concretePrototype.strMessage); 11 Console.WriteLine("keyValuePairs:"); 12 foreach (KeyValuePair<int,string> item in concretePrototype.keyValuePairs) 13 { 14 Console.WriteLine("KEY:{0} Value:{1}", item.Key, item.Value); 15 } 16 17 Console.WriteLine("\r\n"); 18 19 ConcretePrototype concretePrototype2 = (ConcretePrototype)concretePrototype.Clone(); 20 concretePrototype2.strMessage = "BBBBBBBBB"; 21 concretePrototype2.keyValuePairs[1] = "A1"; 22 Console.WriteLine("id:{0}", concretePrototype2.Id); 23 Console.WriteLine("strMessage:{0}", concretePrototype2.strMessage); 24 Console.WriteLine("keyValuePairs:"); 25 foreach (KeyValuePair<int, string> item in concretePrototype2.keyValuePairs) 26 { 27 Console.WriteLine("KEY:{0} Value:{1}", item.Key, item.Value); 28 } 29 30 Console.WriteLine("\r\n"); 31 32 Console.WriteLine("id:{0}", concretePrototype.Id); 33 Console.WriteLine("strMessage:{0}", concretePrototype.strMessage); 34 Console.WriteLine("keyValuePairs:"); 35 foreach (KeyValuePair<int, string> item in concretePrototype.keyValuePairs) 36 { 37 Console.WriteLine("KEY:{0} Value:{1}", item.Key, item.Value); 38 } 39 Console.ReadKey(); 40 } 41 }
View Code上述代碼中,首先創建了一個concretePrototype原型對象,然後給字元串類型的strMessage賦值“AAAAAAAAA”。 然後給引用類型的keyValuePairs字典添加key=1和key=2,值分別是A和B。
通過Clone()方法進行原型對象的複製操作,生成新對象concretePrototype2。
修改新對象中的strMessage屬性和keyValuePairs字典中key=1的值為“A1”。
通過列印出的內容可以看出新對象中的strMessage值修改並不會影響原型對象中的內容,而引用類型keyValuePairs則發生了改變。
通過這個實例可以看出淺複製,對值類型進行全盤拷貝,對引用類型只拷貝了引用地址。
-
修改上述實例,將淺複製改為深複製
1 /// <summary> 2 /// 原型類 3 /// </summary> 4 [Serializable] 5 public abstract class Prototype 6 { 7 ...... 8 } 9 10 /// <summary> 11 /// 創建具體原型 12 /// 如果是要通過序列化來進行深拷貝的話,要打上Serializable標簽 13 /// </summary> 14 [Serializable] 15 public class ConcretePrototype : Prototype 16 { 17 public ConcretePrototype(int id) 18 : base(id) 19 { } 20 21 /// <summary> 22 /// 深拷貝 23 /// </summary> 24 /// <returns>返回一個全新的Person對象</returns> 25 public override Prototype Clone() 26 { 27 //創建一個記憶體流 28 MemoryStream ms = new MemoryStream(); 29 //創建一個二進位序列化對象 30 BinaryFormatter bf = new BinaryFormatter(); 31 //將當前對象序列化寫入ms記憶體流中 32 bf.Serialize(ms, this); 33 //設置流讀取的位置 34 ms.Position = 0; 35 //將流反序列化為Object對象 36 return bf.Deserialize(ms) as Prototype; 37 } 38 }
View Code上述實例通過序列化進行深複製,當然也可以使用反射等技術進行深複製。
運行後可以看出,深複製後引用類型也會生成一個新的地址。
總結:
原型模式就是對對象進行複製操作,而避免重覆進行初始化操作,生產多個克隆對象。
作者:少年真愛 出處:https://www.cnblogs.com/mingnianjiehunba/p/17721835.html 博主的文章沒有高度、深度和廣度,只是湊字數。由於博主的水平不高,不足和錯誤之處在所難免,希望大家能夠批評指出。 博主是利用讀書、參考、引用、抄襲、複製和粘貼等多種方式打造成自己的文章,請原諒博主成為一個無恥的文檔搬運工!