點擊查看:設計模式系列 html
理解:原型模式屬於建立型模式,與工廠,單件,生成器模式有類似點,就是建立對象,而原型模式最大的特色就是對一個基類對象進行克隆複製建立出模型同樣的副本,進行操做。面試
舉例:sql
即將開學啦,就來個入學考試吧數據庫
基對象(通常爲接口,抽象類):考試題(樣卷)c#
原型模式的復職克隆:根據須要印刷考卷,這裏的考卷都是複製考試題樣卷設計模式
客戶端:學生答卷,同一套試卷,學生作題不可能如出一轍數據結構
類圖:ide
接口:試卷樣例代碼this
/// <summary> /// 選答題 /// </summary> public class SelectTest { private string other; public string 你老婆多大 { get { return this.other; } set { this.other = value; } } } /// <summary> /// 面試題 /// </summary> public interface Itest { Itest Clone(); string 知道設計模式嗎 { get; set; } string 設計模式有幾種 { get; set; } string 你知道那些 { get; set; } SelectTest 附加題 { get; set; } Test Test { get; set; } Test Test1 { get; set; } }
複製克隆:複印機spa
/// <summary> /// 繼承Itest接口 /// </summary> public class Test : Itest { private string one; private string two; private string three; private SelectTest other=new SelectTest(); public string 知道設計模式嗎 { get { return this.one; } set { this.one = value; } } public string 設計模式有幾種 { get { return this.two; } set { this.two = value; } } public string 你知道那些 { get { return this.three; } set { this.three = value; } } public SelectTest 附加題 { get { return this.other; } set { this.other = value; } } #region IColorDemo 成員 public Itest Clone() { //克隆當前類 return (Itest)this.MemberwiseClone(); } #endregion }
客戶端,髮捲作題
static void Main() { //印刷試卷 Itest test = new Test(); //複製樣本試卷 Itest test1 = test.Clone(); //考生1 test.設計模式有幾種 = "23"; test.附加題.你老婆多大 = "18"; //考生2 test1.設計模式有幾種 = "24"; test1.附加題.你老婆多大 = "20"; //顯示考生答卷內容 Console.WriteLine("test設計模式有幾種:" + test.設計模式有幾種); //23 Console.WriteLine("test附加題.你老婆多大:" + test.附加題.你老婆多大); //20 Console.WriteLine("test1設計模式有幾種:" + test1.設計模式有幾種); //24 Console.WriteLine("test1附加題.你老婆多大:" + test1.附加題.你老婆多大); //20 Console.ReadKey(); }
注意:這裏兩我的答得不同,爲何附加題中,老婆年齡都爲20?
這裏涉及到深拷貝,淺拷貝問題,值類型是放在棧上的,拷貝以後,會自會在站上從新add一個,而class屬於引用類型,拷貝以後,棧上從新分配啦一個指針,可指針卻指向同一個位置的資源。淺拷貝,只拷貝值類型,深拷貝,引用類型也拷貝複製。
解決方案:
public Itest Clone() { //克隆當前類 Itest itst= (Itest)this.MemberwiseClone(); SelectTest st = new SelectTest(); st.你老婆多大 = this.other.你老婆多大; itst.附加題 = st; return itst; }
使用序列化解決
/// <summary> /// 選答題 /// </summary> [Serializable] public class SelectTest { private string other; public string 你老婆多大 { get { return this.other; } set { this.other = value; } } } /// <summary> /// 面試題 /// </summary> public interface Itest { Itest Clone(); string 知道設計模式嗎 { get; set; } string 設計模式有幾種 { get; set; } string 你知道那些 { get; set; } SelectTest 附加題 { get; set; } } /// <summary> /// 繼承Itest接口 /// </summary> [Serializable] public class Test : Itest { private string one; private string two; private string three; private SelectTest other=new SelectTest(); public string 知道設計模式嗎 { get { return this.one; } set { this.one = value; } } public string 設計模式有幾種 { get { return this.two; } set { this.two = value; } } public string 你知道那些 { get { return this.three; } set { this.three = value; } } public SelectTest 附加題 { get { return this.other; } set { this.other = value; } } public Itest Clone() { SerializableHelper SerializableHelper = new 原型模式.SerializableHelper(); string target = SerializableHelper.Serializable(this); return SerializableHelper.Derializable<Itest>(target); } }
public class SerializableHelper { public string Serializable(object target) { using (MemoryStream stream = new MemoryStream()) { new BinaryFormatter().Serialize(stream, target); return Convert.ToBase64String(stream.ToArray()); } } public object Derializable(string target) { byte[] targetArray = Convert.FromBase64String(target); using (MemoryStream stream = new MemoryStream(targetArray)) { return new BinaryFormatter().Deserialize(stream); } } public T Derializable<T>(string target) { return (T)Derializable(target); } }
原型模式的用處不少,好比如今比較流行的orm技術,修改,編輯前一個原型帶數據的,克隆原型樣例而後對其複製,而後再讓這兩個編輯先後的對象作對比,若是相同就不修改,不一樣則生成sql語句經行update。原型模式的身形仍是很常見的,由於他建立新對象方便快捷,並且可在運行時根據須要經過克隆來添加和去除他們,也可在程序運行是根據狀況來修改類內部的數據,並且運行時無需建立類就可以獲得你想要的新生對象。