設計模式(2)工廠方法模式(Factory Method)

設計模式(0)簡單工廠模式html

設計模式(1)單例模式(Singleton)git

源碼地址github

0 工廠方法模式簡介

0.0 工廠方法模式定義

工廠方法模式是在簡單工廠模式基礎上,爲解決更復雜的對象建立問題而衍生進化出來的一種建立型模式。設計模式

工廠方法模式的核心思想是定義一個用於建立對象的接口,讓其子類去決定去實例化哪一個具體類的對象,工廠方法模式可使一個類的實例化動做延遲到其子類。spa

工廠方法模式結構圖以下設計

1

0.1 工廠方法模式應用場景

還接着祭壇生產英雄的示例,咱們已經在簡單工廠模式一文中經過建立簡單工廠方法類,來實現暗夜精靈種族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

一、隨着英雄的增多,簡單工廠類須要反覆修改。

二、簡單工廠類過於龐大,職責混亂,負責了四個種族全部英雄的建立,而實際上,玩家在進入遊戲時已經選好了本身的種族,只有可能建立所選種族的英雄。

咱們到了這裏,首先要想到的是,既然四個種族,分別有本身的祭壇,產生改種族的英雄,咱們應該將簡單工廠類按照種族進行職責拆分,此時參考上面提到的工廠方法模式定義以及結構圖,咱們會發現,如今是到了工廠方法模式出場的時候了。

1 工廠方法模式詳解

一、提煉工廠方法接口

將原來的簡單工廠類,進一步提煉爲一個工廠方法接口,其包含一個名爲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();
}

1

四、經過反射實例化具體的工廠方法類

在實際應用中跟上面不一樣種族建立英雄的例子相似,通常在系統啓動時就已經肯定要使用哪一種方法實例化工廠方法類,一般咱們能夠將工廠類的實例化經過配置文件的方式肯定,從而避免源碼的修改。

string factoryName = ConfigurationManager.AppSettings["FactoryName"]; // 讀取配置文件
IFactory factory = (IFactory)Assembly.Load("FactoryMethodPattern").CreateInstance("FactoryMethodPattern." + factoryName); // 實例化配置的工廠方法類

2 總結

工廠方法模式具備如下優勢

一、更容易對現有功能進行擴展,若是有新的需求,只須要實現一個相應的工廠方法實現類便可,無需修改現有代碼。

二、不一樣工廠方法類,實現了單一職責的設計原則。

工廠方法模式的缺點

因爲具體的對象由具體指定的工廠方法類建立,致使具體產品和工廠方法類之間具備較強的耦合性

相關文章
相關標籤/搜索