設計模式(0)簡單工廠模式 設計模式(1)單例模式(Singleton) 源碼地址 0 工廠方法模式簡介 0.0 工廠方法模式定義 工廠方法模式是在簡單工廠模式基礎上,為解決更複雜的對象創建問題而衍生進化出來的一種創建型模式。 工廠方法模式的核心思想是定義一個用於創建對象的介面,讓其子類去決定去實例 ...
0 工廠方法模式簡介
0.0 工廠方法模式定義
工廠方法模式是在簡單工廠模式基礎上,為解決更複雜的對象創建問題而衍生進化出來的一種創建型模式。
工廠方法模式的核心思想是定義一個用於創建對象的介面,讓其子類去決定去實例化哪個具體類的對象,工廠方法模式可以使一個類的實例化動作延遲到其子類。
工廠方法模式結構圖如下
0.1 工廠方法模式應用場景
還接著祭壇生產英雄的示例,我們已經在簡單工廠模式一文中通過創建簡單工廠方法類,來實現暗夜精靈種族4個英雄的創建
/// <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; } }
假設現在我們要創建不死族的英雄怎麼辦呢,如果依然使用簡單工廠方法類,則首先需要實現不死族四個英雄類。
/// <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; } }
還有獸族及人族,也需要如此修改。到此我們會感覺存在有以下問題
1、隨著英雄的增多,簡單工廠類需要反覆修改。
2、簡單工廠類過於龐大,職責混亂,負責了四個種族所有英雄的創建,而實際上,玩家在進入游戲時已經選好了自己的種族,只有可能創建所選種族的英雄。
我們到了這裡,首先要想到的是,既然四個種族,分別有自己的祭壇,產生改種族的英雄,我們應該將簡單工廠類按照種族進行職責拆分,此時參考上面提到的工廠方法模式定義以及結構圖,我們會發現,現在是到了工廠方法模式出場的時候了。
1 工廠方法模式詳解
1、提煉工廠方法介面
將原來的簡單工廠類,進一步提煉為一個工廠方法介面,其包含一個名為CreateHero的介面。
/// <summary> /// 工廠方法介面 /// </summary> public interface IFactory { /// <summary> /// 創建英雄的方法 /// </summary> /// <param name="heroName">英雄名稱</param> /// <returns></returns> IHero CreateHero(string heroName); }
2、實現四個種族的工廠方法
四個種族創建英雄的工廠方法繼承自工廠方法介面,實現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; } } }
3、客戶端調用
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(); }
4、通過反射實例化具體的工廠方法類
在實際應用中跟上面不同種族創建英雄的例子類似,一般在系統啟動時就已經確定要使用哪種方法實例化工廠方法類,通常我們可以將工廠類的實例化通過配置文件的方式確定,從而避免源碼的修改。
string factoryName = ConfigurationManager.AppSettings["FactoryName"]; // 讀取配置文件 IFactory factory = (IFactory)Assembly.Load("FactoryMethodPattern").CreateInstance("FactoryMethodPattern." + factoryName); // 實例化配置的工廠方法類
2 總結
工廠方法模式具有以下優點
1、更容易對現有功能進行擴展,如果有新的需求,只需要實現一個相應的工廠方法實現類即可,無需修改現有代碼。
2、不同工廠方法類,實現了單一職責的設計原則。
工廠方法模式的缺點
由於具體的對象由具體指定的工廠方法類創建,導致具體產品和工廠方法類之間具有較強的耦合性