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

来源:http://www.cnblogs.com/fonour/archive/2017/06/21/7055737.html
-Advertisement-
Play Games

設計模式(0)簡單工廠模式 設計模式(1)單例模式(Singleton) 源碼地址 0 工廠方法模式簡介 0.0 工廠方法模式定義 工廠方法模式是在簡單工廠模式基礎上,為解決更複雜的對象創建問題而衍生進化出來的一種創建型模式。 工廠方法模式的核心思想是定義一個用於創建對象的介面,讓其子類去決定去實例 ...


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

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

源碼地址

0 工廠方法模式簡介

0.0 工廠方法模式定義

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

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

工廠方法模式結構圖如下

1

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();
}

1

4、通過反射實例化具體的工廠方法類

在實際應用中跟上面不同種族創建英雄的例子類似,一般在系統啟動時就已經確定要使用哪種方法實例化工廠方法類,通常我們可以將工廠類的實例化通過配置文件的方式確定,從而避免源碼的修改。

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

2 總結

工廠方法模式具有以下優點

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

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

工廠方法模式的缺點

由於具體的對象由具體指定的工廠方法類創建,導致具體產品和工廠方法類之間具有較強的耦合性


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 參考之一:Linux 線程同步的三種方法 鏈接地址:http://www.cnblogs.com/eleclsc/p/5838790.html 簡要回答: Linux下線程同步最常用的三種方法就是互斥鎖、條件變數及信號量。 互斥鎖通過鎖機制來實現線程間的同步,鎖機制是同一時刻只允許一個線程執行一個關 ...
  • Given a collection of integers that might contain duplicates, nums, return all possible subsets. ...
  • String s = null; s += "hello"; System.out.println(s); 結果為:nullhello 原因: 先應用String.valueOf 得出s的value值,再通過StringBuilder拼接hello,因此將value與hello進行了拼接; Stri ...
  • 1、簡單解釋就是:反轉一個序列對象 例子1: def fun3(): x = [3,6,9] for i in reversed(x): print(i,end=',')fun3() 輸出: 》》》9,6,3, 例子2: >>> a = range(5)>>> arange(0, 5)>>> lis ...
  • /* 標識映射在數據映射器的基礎上增加了標識映射類,主要功能是保存已經創建好的對象,在需要的時候可以直接獲取而不是重覆創建造成系統性能的下降。 在數據映射器基礎上還增加了部分調用標識映射類的方法,示例代碼如下: */ namespace woo\domain; //標識映射類 class Objec... ...
  • 梳排序的知名度遠沒有其他排序演算法那麼高,它是在冒泡排序的基礎上做的改進,引入類似“步長”以及“子序列”概念,這兩個概念在後面的排序演算法中會經常提及。 待排序列:{10, 2, 11, 8, 7} groupNums = length = 5 步長繫數(分組繫數)coefficient = 1.3 排 ...
  • 下載sbt: http://www.scala-sbt.org/download.html 解壓zip文件F:\sbt-0.13.15 配置環境變數 如果需要可以修改F:\sbt-0.13.15\sbt\conf\sbtconfig.txt #ivy的cache等,保存到指定的文件夾;不配置的話sb ...
  • 題目背景 [Usaco2008 Jan] 題目描述 N (1 ≤ N ≤ 100) cows, conveniently numbered 1..N, are participating in a programming contest. As we all know, some cows code ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...