【23種設計模式】工廠方法模式(二)

来源:https://www.cnblogs.com/wml-it/archive/2023/08/27/17660891.html
-Advertisement-
Play Games

****## 前言 在講述之工廠方法模式前,我們來先瞭解簡單工廠模式,簡單工廠模式是最簡單的設計模式之一,它雖然不屬於GoF的23種設計模式,但是應用也較為頻繁,同時它也是學習其他創建型模式的基礎。下麵我們來先瞭解下簡單工廠模式,然後針對它的缺點來引出工廠方法模式。 ## 簡單工廠模式定義 **簡單 ...


****## 前言

在講述之工廠方法模式前,我們來先瞭解簡單工廠模式,簡單工廠模式是最簡單的設計模式之一,它雖然不屬於GoF的23種設計模式,但是應用也較為頻繁,同時它也是學習其他創建型模式的基礎。下麵我們來先瞭解下簡單工廠模式,然後針對它的缺點來引出工廠方法模式。

簡單工廠模式定義

簡單工廠模式簡單來說就是創建一個工廠類,通過輸入的參數創建對象賦值給基類,完成對想要的派生類的調用,從而達成目標,具體的操作均在子類中完成,工廠類只負責運算邏輯和給基類賦值。在簡單工廠模式中,只需要記住一個簡單的參數即可獲得所需的對象實例,它提供專門的核心工廠類來負責對象的創建,實現對象的創建和使用分離。該模式有三部分:
image

  • 工廠方法類:實現創建所有實例的選擇類型,被外界調用的介面。
  • 抽象父類:所要創建的類的基類,描述類所有實例所共有的公共介面(方法),可以是抽象類也可是介面類型(interface),本例是抽象類。
  • 具體子類:所有要創建的具體實例對象。

簡單工廠模式代碼實現

抽象產品類和工廠類合併,將靜態工廠方法移到抽象產品類中,根據不同的參數創建不同類型的產品子類對象。只需要添加配置文件並更改相關參數讀取參數即可,不要重新編譯程式。

  • 引入NuGet包:System.Configuration.ConfigurationManager
    image

  • 添加配置文件:App.config文件,追加內容

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
    	<appSettings>
    		<!--節點下添加配置,根據此配置,讀取參數決定創建哪個Product-->
    		<add key="Product" value="B" />
    	</appSettings>
    </configuration>
    
  • 創建抽象父類和具體子類
    抽象類:包含工廠方法

     /// <summary>
        /// 【01】抽象工廠類
        /// </summary>
        public abstract class Product
        {
            /// <summary>
            /// 靜態工廠方法
            /// </summary>
            /// <param name="arg"></param>
            /// <returns></returns>
            public static Product GetProduct(string arg)
            {
                Product product = null;
                switch (arg)
                {
                    case "A":
                        product = new ProduceA();
                        break;
                    case "B":
                        product = new ProduceB();
                        break;
                        //註意:有新產品需要修改工廠方法和創建新具體產品
                    default:
                        throw new ArgumentException(message: "參數不合法");
                }
                return product;
            }
            /// <summary>
            /// 所有產品類的公共業務方法
            /// </summary>
            public void MethodSame()
            {
                Console.WriteLine("公共業務方法");
            }
            /// <summary>
            /// 聲明抽象業務方法
            /// </summary>
            public abstract void MethodDiff();
        }
    

    具體子類:

     /// <summary>
        ///【02】具體工廠類A
        /// </summary>
        public class ProduceA : Product
        {
            /// <summary>
            /// 實現業務方法
            /// </summary>
            public override void MethodDiff()
            {
                Console.WriteLine("產品A處理業務方法");
            }
        }
    
       /// <summary>
        ///【03】具體工廠類B
        /// </summary>
        public class ProduceB : Product
        {
            /// <summary>
            /// 實現業務方法
            /// </summary>
            public override void MethodDiff()
            {
                Console.WriteLine("產品B處理業務方法");
            }
        }
    
  • 調用

      		/// <summary>
            /// 調用測試方法
            /// </summary>
            public void RunTest()
            {
                //客戶端調用
                var type = ConfigurationManager.AppSettings["product"];//根據配置文件中參數,傳入工廠方法,決定創建具體Product
                Product oneProduct = Product.GetProduct(type);
                oneProduct.MethodSame();
                oneProduct.MethodDiff();
    
            }
    

簡單工廠模式的優缺點

優點:

  • 工廠類包含必要的邏輯判斷,可以決定在什麼時候創建哪一個產品類的實例,客戶端可以免除直接創建產品對象的職責,而僅僅“消費”產品,
  • 簡單工廠模式實現了對象創建和使用的分離。
  • 客戶端無須知道所創建的具體產品類的類名,只需知道具體產品類所對應的參數即可。
  • 通過引入配置文件,可以在不修改任何客戶端代碼的情況下,更換和增加新的具體產品類,在一定程度上提高了系統的靈活性。

缺點:

  • 由於工廠類集中了所有產品的創建邏輯,職責過重,一旦不能正常工作,整個系統都要受到影響。
  • 使用簡單工廠模式勢必會增加系統中類的個數,增加了系統的複雜度和理解難度。
  • 系統擴展難度,一旦添加新產品不得不修改工廠邏輯,在產品類型加多時,有可能造成工廠邏輯過於複雜,不利於系統的擴展與維護。
  • 簡單工廠模式由於使用了靜態工廠方法,造成工廠角色無法形成基於繼承的等級結構。

簡單工廠模式小結

簡單工廠模式中,我們也發現了它的缺點,就是隨著需求的變化我們要不停地修改工廠裡面的方法的代碼,需求變化越多,裡面的If–Else–也越多,這樣就會造成簡單工廠的實現邏輯過於複雜。設計模式是遵循一定原則而得來的,比如,我們要怎麼增加代碼,怎麼修改代碼,其中一個原則就是OCP原則,中文是【開放關閉原則】,對增加代碼開放,對修改代碼關閉,所以我們就不能總是這樣修改簡單工廠裡面的方法。

工廠方法模式定義

工廠方法模式可以解決簡單工廠模式中存在的這個問題,定義一個用於創建對象的介面,讓子類決定實例化哪一個類。Factory Method使得一個類的實例化延遲到子類。
image

可以看出,在工廠方法模式的結構圖有以下角色:

  • 抽象工廠(Creator): 充當抽象工廠角色,定義工廠類所具有的基本的操作,任何具體工廠都必須繼承該抽象類。

  • 具體工廠(CreatorA):充當具體工廠角色,該類必須繼承抽象工廠角色,實現抽象工廠定義的方法,用來創建具體車。

  • 抽象車(Car):充當抽象車角色,定義車類型所有具有的基本操作,具體車必須繼承該抽象類。

  • 具體車(CarA):充當具體車角色,實現抽象車類對定義的抽象方法,由具體工廠類創建,它們之間有一一對應的關係。

簡單工廠模式的問題是:如果有新的需求,就需要修改工廠類裡面創建產品對象實例的那個方法的實現代碼,在面向對象設計一個原則就是哪裡有變化,我就封裝哪裡。

工廠方法模式代碼實現

  • 抽象汽車類

      /// <summary>
        /// 汽車抽象類
        /// </summary>
        public abstract class Car
        {
            /// <summary>
            /// 開始行駛
            /// </summary>
            public abstract void Go();
        }
    
  • 具體汽車類

     /// <summary>
        /// ConcreteCar 具體車輛類
        /// </summary>
        public class ConcreteCar
        {
            /// <summary>
            /// 紅旗汽車
            /// </summary>
            public class HongQiCar : Car
            {
                public override void Go()
                {
                    Console.WriteLine("紅旗汽車開始行駛了!");
                }
            }
    
            /// <summary>
            /// 奧迪汽車
            /// </summary>
            public class AoDiCar : Car
            {
                public override void Go()
                {
                    Console.WriteLine("奧迪汽車開始行駛了");
                }
            }
        }
    
  • 抽象工廠

      /// <summary>
        /// 抽象工廠類
        /// </summary>
        public abstract class Factory
        {
            /// <summary>
            /// 工廠方法
            /// </summary>
            /// <returns></returns>
            public abstract Car CreateCar();
        }
    
  • 具體工廠

     /// <summary>
        /// ConcreteFactory  具體工廠方法
        /// </summary>
        public class ConcreteFactory
        {
            /// <summary>
            /// 紅旗汽車工廠類
            /// </summary>
            public class HongQiCarFactory : Factory
            {
                /// <summary>
                /// 負責生產紅旗汽車
                /// </summary>
                /// <returns></returns>
                public override Car CreateCar()
                {
                    return new HongQiCar();
                }
            }
    
            /// <summary>
            /// 奧迪汽車工廠類
            /// </summary>
            public class AoDiCarFactory : Factory
            {
                /// <summary>
                /// 負責創建奧迪汽車
                /// </summary>
                /// <returns></returns>
                public override Car CreateCar()
                {
                    return new AoDiCar();
                }
            }
        }
    
  • 調用

    		 /// <summary>
            /// 測試方法
            /// </summary>
            public void RunTest()
            {
                // 初始化創建汽車的兩個工廠
                Factory hongQiCarFactory = new HongQiCarFactory();
                Factory aoDiCarFactory = new AoDiCarFactory();
    
                // 生產一輛紅旗汽車
                Car hongQi = hongQiCarFactory.CreateCar();
                hongQi.Go();
    
                //生產一輛奧迪汽車
                Car aoDi = aoDiCarFactory.CreateCar();
                aoDi.Go();
            }
    

工廠方法模式優缺點

優點:

  • 在工廠方法中,用戶只需要知道所要產品的具體工廠,無須關係具體的創建過程,甚至不需要具體產品類的類名。
  • 在系統增加新的產品時,我們只需要添加一個具體產品類和對應的實現工廠,無需對原工廠進行任何修改,很好地符合了“開閉原則”。

缺點:

  • 每次增加一個產品時,都需要增加一個具體類和對象實現工廠,是的系統中類的個數成倍增加,在一定程度上增加了系統的複雜度,同時也增加了系統具體類的依賴。這並不是什麼好事。

本文來自博客園,作者:碼農阿亮,轉載請註明原文鏈接:https://www.cnblogs.com/wml-it/p/17660891.html


技術的發展日新月異,隨著時間推移,無法保證本博客所有內容的正確性。如有誤導,請大家見諒,歡迎評論區指正!
開源庫地址,歡迎點亮:
GitHub:https://github.com/ITMingliang
Gitee:   https://gitee.com/mingliang_it
GitLab: https://gitlab.com/ITMingliang

建群聲明: 本著技術在於分享,方便大家交流學習的初心,特此建立【編程內功修煉交流群】,為大家答疑解惑。熱烈歡迎各位愛交流學習的程式員進群,也希望進群的大佬能不吝分享自己遇到的技術問題和學習心得!進群方式:掃碼關註公眾號,後臺回覆【進群】。



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

-Advertisement-
Play Games
更多相關文章
  • 最近接觸到了 [github.com/json-iterator/go](https://github.com/json-iterator/go) , 是由滴滴開源的第三方json編碼庫,它同時提供Go和Java兩個版本。 > 文中大量內容來自 github 上的 wiki 文檔,有興趣的朋友可以直 ...
  • [原題](https://www.luogu.com.cn/problem/UVA908) ## 1.題意分析 題意就是給你很多組數,對於每組數,有三組小數據。第一組小數據先輸入一個n表示頂點數,然後再輸入n-1條邊表示初始邊數。其它組小數據先輸入一個數k,表示增加的邊的數量,然後再輸入k條邊,表示 ...
  • ## 概述 Spring Cloud Zuul 是 Spring Cloud Netflix 子項目的核心組件之一,可以作為微服務架構中的 API 網關使用,有以下用途: - 鑒權:對於訪問每個服務的請求進行鑒權,拒絕鑒權失敗的請求 - 監控:對系統的請求進行監控,記錄請求響應日誌,實時統計當前系統 ...
  • RocketMQ 是一個純 Java、分散式、隊列模型的開源消息中間件;前身是 MetaQ,是阿裡參考 Kafka 研發的一個隊列模型的消息中間件,後開源給 Apache 基金會併成為 Apache 的頂級項目,具有高性能、高可靠、高實時、分散式的特點。 1、基本概念 1.1、主題(Topic) A ...
  • ### 歡迎訪問我的GitHub > 這裡分類和彙總了欣宸的全部原創(含配套源碼):[https://github.com/zq2599/blog_demos](https://github.com/zq2599/blog_demos) ### 關於IDEA的預覽版 - IDEA會啟用新的UI,這事 ...
  • 本文將分享使用 GitHub Actions 完成對一個.Net Core+Vue 的前後端分離項目 zhontai 的構建,並使用 docker 部署到雲伺服器(阿裡雲),及對docker部署.Net Core+Vue的一些經驗分享。 ...
  • AgileConfig 已經好久好久沒有更新過比較大的功能了。一是 AgileConfig 本身的定位就是比較輕量,不想集成太多的功能。二是比較忙(懶)。但是本次升級給大家帶來了一個比較有用的功能 SSO。 ![](https://static.xbaby.xyz/%E5%BE%AE%E4%BF%A ...
  • TDengine 是國內比較流的時序庫之一,支持群集並且免費,在.NET中資料比較少,這篇文章主要介紹SqlSugar ORM來操作TDengine 優點: 1、SqlSugar支持ADO.NET操作來實現TDengine,並且支持了常用的時間函數、支持聯表、分頁和批量插入和刪等操作 2、使用了原生 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...