設計模式(0)簡單工廠模式html
設計模式(2)工廠方法模式(Factory Method)github
設計模式(3)抽象工廠模式(Abstract Factory)設計模式
源碼地址spa
原型模式是一種經常使用的建立型模式,原型模式的通常定義爲用原型實例指定建立對象的種類,並經過拷貝這些原型建立新的對象設計
原型模式要求對象必須具備一個能夠「克隆」自身的方法,這樣就能夠經過這個克隆自身的方法建立一個新的同一類型的實例。咱們一般將這個克隆自身的方法定義在抽象的接口上,直接經過接口調用其內部包含的克隆方法,建立一個具體的對象。這樣就能夠實現經過原型模式建立具體對象,無需關注這個對象自己的類型,也不用關心其內部的具體實現,而無須再去經過new去建立具體的類型的實例。code
原型模式的結構圖以下htm
Prototype:聲明一個克隆自身的接口,用來約束想要克隆自身的類,全部想要實現克隆自身這一功能的類須要繼承此接口,而且實現該接口裏定義的克隆自身的方法對象
ConcretePrototype:實現了Prototype接口的具體實現類,這些類中負責Clone這一方法的具體實現
Client:客戶端,經過原型實例克隆自身的Clone方法建立新的對象實例
在war3中,有一個道具叫作「幻象權杖」其做用是使用後能製造目標單位的一個幻象。咱們不考究幻象的其餘具體細節,從外形上是與本體徹底一摸同樣的。
咱們先建立一個英雄的接口
/// <summary> /// 英雄接口定義 /// </summary> public interface IHero { /// <summary> /// 身體特徵 /// </summary> string Body { get; set; } /// <summary> /// 武器 /// </summary> string Weapon { get; set; } /// <summary> /// 坐騎 /// </summary> string Mount { get; set; } }
DH類具體實現
/// <summary> /// 惡魔獵手 /// </summary> public class DH : IHero { /// <summary> /// 身體特徵 /// </summary> public string Body { get { return "黑夜給了我黑色眼睛,我卻用它去尋找光明。"; } set { } } /// <summary> /// 武器 /// </summary> public string Weapon { get { return "艾辛諾斯雙刃。"; } set { } } /// <summary> /// 坐騎 /// </summary> public string Mount { get { return "我有這雙腳有這雙腿。"; } set { } } }
POM類具體實現
/// <summary> /// 月亮女祭司 /// </summary> public class POM : IHero { /// <summary> /// 身體特徵 /// </summary> public string Body { get { return "夜幕只爲朱顏改,羣星隕落無窮。"; } set { } } /// <summary> /// 武器 /// </summary> public string Weapon { get { return "索利達爾·羣星之怒。"; } set { } } /// <summary> /// 坐騎 /// </summary> public string Mount { get { return "艾斯卡達爾。"; } set { } } }
幻象權杖類實現
/// <summary> /// 幻象權杖 /// </summary> public class WandOfIllusion { public static IHero Use(IHero hero) { IHero result = null; if (hero is DH) { result = new DH(); } else if (hero is POM) { result = new POM(); } return result; } }
客戶端使用
class Program { static void Main(string[] args) { DH dh = new DH(); var dh1 = WandOfIllusion.Use(dh); // 對dh使用幻象權杖 Console.ReadLine(); } }
這樣能夠實現英雄使用幻象權杖複製自身這一基本需求,可是明顯存在一下問題
一、經過幻象權杖複製英雄對象自己 這一通用的功能代碼中,不該該強依賴具體的英雄類,應該是與具體的實現無關的。
二、難以擴展,要實現其餘英雄使用幻象權杖這一操做,就必須修改幻象權杖類,裏面須要增長更多的類型判斷。並且咱們這裏只作了簡要的對象建立處理,而實際中各個對象的建立過程是千差萬別的,這樣咱們的幻象權杖類就會變得愈來愈難以維護。
基於問題的出現以及上述對原型模式的介紹,咱們可使用原型模式解決這一問題。
0、英雄接口增長Clone方法
按照原型模式的要求,咱們須要在英雄接口中增長一個Clone方法,全部英雄的具體實現類實現此方法,完成複製英雄的具體細節。
/// <summary> /// 英雄接口定義 /// </summary> public interface IHero { /// <summary> /// 身體特徵 /// </summary> string Body { get; set; } /// <summary> /// 武器 /// </summary> string Weapon { get; set; } /// <summary> /// 坐騎 /// </summary> string Mount { get; set; } /// <summary> /// Clone自己接口定義 /// </summary> /// <returns></returns> IHero Clone(); }
一、具體英雄實現類實現Clone方法
/// <summary> /// 惡魔獵手 /// </summary> public class DH : IHero { /// <summary> /// 身體特徵 /// </summary> public string Body { get { return "黑夜給了我黑色眼睛,我卻用它去尋找光明。"; } set { } } /// <summary> /// 武器 /// </summary> public string Weapon { get { return "艾辛諾斯雙刃。"; } set { } } /// <summary> /// 坐騎 /// </summary> public string Mount { get { return "我有這雙腳有這雙腿。"; } set { } } /// <summary> /// Clone /// </summary> /// <returns></returns> public IHero Clone() { IHero hero = new DH(); //TODO:進行其餘Clone相關操做 return hero; } }
/// <summary> /// 月亮女祭司 /// </summary> public class POM : IHero { /// <summary> /// 身體特徵 /// </summary> public string Body { get { return "夜幕只爲朱顏改,羣星隕落無窮。"; } set { } } /// <summary> /// 武器 /// </summary> public string Weapon { get { return "索利達爾·羣星之怒。"; } set { } } /// <summary> /// 坐騎 /// </summary> public string Mount { get { return "艾斯卡達爾。"; } set { } } /// <summary> /// Clone /// </summary> /// <returns></returns> public IHero Clone() { IHero hero = new POM(); //TODO:進行其餘Clone相關操做 return hero; } }
二、修改幻象權杖類
/// <summary> /// 幻象權杖 /// </summary> public class WandOfIllusion { public static IHero Use(IHero hero) { IHero result = null; //if (hero is DH) //{ // result = new DH(); //} //else if (hero is POM) //{ // result = new POM(); //} result = hero.Clone(); return result; } }
至此咱們的幻象權杖通用類,已經與具體的英雄實現類無關了。
三、淺克隆和深克隆
淺克隆:只克隆值類型的屬性數據
深克隆:除了要複製淺克隆須要複製的值類型屬性數據外,也要複製引用類型的屬性數據。
優勢
對客戶端調用隱藏具體實現類細節,減小外部調用對具體實現類的依賴
缺點
每一個實現類都必須實現Clone方法,尤爲在包含引用類型的深克隆時,須要逐級讓全部的引用類型實現Clone