設計模式(0)簡單工廠模式html
源碼地址github
工廠方法模式是在簡單工廠模式基礎上,爲解決更復雜的對象建立問題而衍生進化出來的一種建立型模式。設計模式
工廠方法模式的核心思想是定義一個用於建立對象的接口,讓其子類去決定去實例化哪一個具體類的對象,工廠方法模式可使一個類的實例化動做延遲到其子類。spa
工廠方法模式結構圖以下設計
還接着祭壇生產英雄的示例,咱們已經在簡單工廠模式一文中經過建立簡單工廠方法類,來實現暗夜精靈種族4個英雄的建立code
/// <summary> /// 建立英雄的靜態方法 /// </summary> /// <param name="heroName">英雄名稱</param> /// <returns></returns> public static IHero CreateHero(string heroName) { switch (heroName) { case "DH": return new DH(); case "WD": return new WD(); case "KOG": return new KOG(); case "POM": return new POM(); default: return null; } }
假設如今咱們要建立不死族的英雄怎麼辦呢,若是依然使用簡單工廠方法類,則首先須要實現不死族四個英雄類。htm
/// <summary> /// 死亡騎士 /// </summary> public class DK : IHero { /// <summary> /// 秀出本身的技能 /// </summary> public void ShowSkills() { Console.WriteLine("我是死亡騎士,我會死亡纏繞、死亡契約、邪惡光環和操縱死屍。"); } }
/// <summary> /// 巫妖 /// </summary> public class Lich : IHero { /// <summary> /// 秀出本身的技能 /// </summary> public void ShowSkills() { Console.WriteLine("我是巫妖,我會霜凍新星、寒冰甲、黑暗儀式和死亡凋零。"); } }
/// <summary> /// 地穴領主 /// </summary> public class DL : IHero { /// <summary> /// 秀出本身的技能 /// </summary> public void ShowSkills() { Console.WriteLine("我是地穴領主,我會穿刺、刺盾、腐蝕甲蟲和蝗羣。"); } }
/// <summary> /// 恐懼魔王 /// </summary> public class CL : IHero { /// <summary> /// 秀出本身的技能 /// </summary> public void ShowSkills() { Console.WriteLine("我是恐懼魔王,我會腐臭羣蜂、睡眠、吸血光環、地獄火。"); } }
而後須要修改工廠方法,增長switch語句中的類型,將不死族四個英雄建立邏輯添加進去。對象
/// <summary> /// 建立英雄的靜態方法 /// </summary> /// <param name="heroName">英雄名稱</param> /// <returns></returns> public static IHero CreateHero(string hero { switch (heroName) { //暗夜精靈 case "DH": return new DH(); case "WD": return new WD(); case "KOG": return new KOG(); case "POM": return new POM(); // 不死族 case "DK": return new DK(); case "Lich": return new Lich(); case "CL": return new CL(); case "DL": return new DL(); default: return null; } }
還有獸族及人族,也須要如此修改。到此咱們會感受存在有如下問題blog
一、隨着英雄的增多,簡單工廠類須要反覆修改。
二、簡單工廠類過於龐大,職責混亂,負責了四個種族全部英雄的建立,而實際上,玩家在進入遊戲時已經選好了本身的種族,只有可能建立所選種族的英雄。
咱們到了這裏,首先要想到的是,既然四個種族,分別有本身的祭壇,產生改種族的英雄,咱們應該將簡單工廠類按照種族進行職責拆分,此時參考上面提到的工廠方法模式定義以及結構圖,咱們會發現,如今是到了工廠方法模式出場的時候了。
一、提煉工廠方法接口
將原來的簡單工廠類,進一步提煉爲一個工廠方法接口,其包含一個名爲CreateHero的接口。
/// <summary> /// 工廠方法接口 /// </summary> public interface IFactory { /// <summary> /// 建立英雄的方法 /// </summary> /// <param name="heroName">英雄名稱</param> /// <returns></returns> IHero CreateHero(string heroName); }
二、實現四個種族的工廠方法
四個種族建立英雄的工廠方法繼承自工廠方法接口,實現CreateHero。
/// <summary> /// 暗夜精靈種族英雄工廠類 /// </summary> public class NEFactory : IFactory { /// <summary> /// 建立英雄的靜態方法 /// </summary> /// <param name="heroName">英雄名稱</param> /// <returns></returns> public IHero CreateHero(string heroName) { switch (heroName) { //暗夜精靈 case "DH": return new DH(); case "WD": return new WD(); case "KOG": return new KOG(); case "POM": return new POM(); default: return null; } } }
/// <summary> /// 不死族英雄工廠類 /// </summary> public class UDFactory : IFactory { /// <summary> /// 建立英雄的靜態方法 /// </summary> /// <param name="heroName">英雄名稱</param> /// <returns></returns> public IHero CreateHero(string heroName) { switch (heroName) { // 不死族 case "DK": return new DK(); case "Lich": return new Lich(); case "CL": return new CL(); case "DL": return new DL(); default: return null; } } }
三、客戶端調用
static void Main(string[] args) { IFactory factory = new NEFactory(); // 初始化一個暗夜精靈族的英雄工廠 Console.WriteLine("我在開局時選擇了暗夜精靈族,個人首發英雄是DH。"); IHero dh = factory.CreateHero("DH"); dh.ShowSkills(); factory = new UDFactory(); // 初始化一個不死族的英雄工廠 Console.WriteLine("我在開局時選擇了不死族,個人首發英雄是DK。"); IHero dk = factory.CreateHero("DK"); dk.ShowSkills(); Console.ReadLine(); }
四、經過反射實例化具體的工廠方法類
在實際應用中跟上面不一樣種族建立英雄的例子相似,通常在系統啓動時就已經肯定要使用哪一種方法實例化工廠方法類,一般咱們能夠將工廠類的實例化經過配置文件的方式肯定,從而避免源碼的修改。
string factoryName = ConfigurationManager.AppSettings["FactoryName"]; // 讀取配置文件 IFactory factory = (IFactory)Assembly.Load("FactoryMethodPattern").CreateInstance("FactoryMethodPattern." + factoryName); // 實例化配置的工廠方法類
工廠方法模式具備如下優勢
一、更容易對現有功能進行擴展,若是有新的需求,只須要實現一個相應的工廠方法實現類便可,無需修改現有代碼。
二、不一樣工廠方法類,實現了單一職責的設計原則。
工廠方法模式的缺點
因爲具體的對象由具體指定的工廠方法類建立,致使具體產品和工廠方法類之間具備較強的耦合性