設計模式中的那些工廠

来源:https://www.cnblogs.com/weihanli/archive/2020/07/12/factory-patterns.html
-Advertisement-
Play Games

設計模式中的那些工廠 Intro 設計模式中有幾個工廠模式,聊一聊這幾個工廠模式的各自用法和使用示例,工廠模式包含簡單工廠,抽象工廠,工廠方法,這些均屬於創建型模式, 所謂創建型模式,就是說這幾個設計模式是用來創建對象的。 簡單工廠 首先來說一說,最簡單的簡單工廠 簡單工廠模式是由一個工廠對象決定創 ...


設計模式中的那些工廠

Intro

設計模式中有幾個工廠模式,聊一聊這幾個工廠模式的各自用法和使用示例,工廠模式包含簡單工廠,抽象工廠,工廠方法,這些均屬於創建型模式,
所謂創建型模式,就是說這幾個設計模式是用來創建對象的。

簡單工廠

首先來說一說,最簡單的簡單工廠

簡單工廠模式是由一個工廠對象決定創建出哪一種產品類的實例

嚴格的來說,簡單工廠模式是工廠模式家族中最簡單實用的模式,但不屬於23種 GOF 設計模式之一。因為每次要新增類型的時候必須修改工廠內部代碼,不符合開閉原則。

來看一個例子:

public class OperationFactory
{
    public static Operation CreateOperation(string operate)
    {
        Operation operation = null;
        switch (operate)
        {
            case "+":
                operation = new OperationAdd();
                break;

            case "-":
                operation = new OpertaionSub();
                break;

            case "*":
                operation = new OperationMul();
                break;

            case "/":
                operation = new OperationDiv();
                break;
        }
        return operation;
    }
}

這是一個簡單的計算器的示例,支持簡單的加減乘除操作,如果要增加一個操作的話就必須要有增加一個 switch ... case 分支,需要修改 CreateOperation 方法不能滿足對擴展開放對修改關閉的開閉原則,所以普遍地認為簡單工廠不屬於設計模式之一,但是我覺得有時候簡單的業務處理用簡單工廠還是比較方便的。

抽象工廠

抽象工廠模式,提供一系列相關或相互依賴對象的介面,而無需指定他們具體的類。

實現抽象工作模式所需要的組件,主要部分:

  • 抽象工廠/抽象產品
  • 具體工廠1/具體產品1
  • 具體工廠2/具體產品2
  • ...

在客戶端根據不同的配置選擇不同的工廠,例如根據配置的資料庫類型的不同選擇使用 Access 資料庫倉儲的工廠還是使用 SqlServer 資料庫的倉儲工廠

示例:

IDbFactory factory = new AccessFactory();
var userRepo = factory.CreateUserRepo();
userRepo.Insert(null);
var departmentRepo = factory.CreateDepartmentRepo();

factory = new SqlServerFactory();
userRepo = factory.CreateUserRepo();
userRepo.Insert(null);

工廠方法

工廠方法模式(Factory Method)定義一個用於創建對象的介面,讓子類決定實例化哪一個類。工廠方法使一個類的實例化延遲到子類。

工廠方法模式實現時,客戶端需要決定實例化哪一個工廠來實現客戶端的操作,也會存在著選擇判斷的問題,不過和簡單工廠相比,簡單工廠的選擇判斷是在工廠內部,而工廠方法則將選擇判斷轉移到了客戶端。

示例:

ILeifengFactory factory = new UndergraduteFactory();
var studentLeifeng = factory.CreateLeifeng();
studentLeifeng.BuyRice();

factory = new VolunteerFactory();
var leifeng1 = factory.CreateLeifeng();
leifeng1.Sweep();

More

工廠模式的作用無外乎下麵這四個。這也是判斷要不要使用工廠模式的最本質的參考標準。

  • 封裝變化:創建邏輯有可能變化,封裝成工廠類之後,創建邏輯的變更對調用者透明。
  • 代碼復用:創建代碼抽離到獨立的工廠類之後可以復用。
  • 隔離複雜性:封裝複雜的創建邏輯,調用者無需瞭解如何創建對象。
  • 控制複雜度:將創建代碼抽離出來,讓原本的函數或類職責更單一,代碼更簡潔。

工廠方法和抽象工廠的區別

工廠方法模式:定義一個用於創建對象的介面,讓子類決定實例化哪一個類
抽象工廠模式:為創建一組相關或相互依賴的對象提供一個介面,而且無需指定他們的具體類
區別在於產品,如果產品單一,最合適用工廠模式,但是如果有多個業務品種、業務分類時,通過抽象工廠模式產生需要的對象是一種非常好的解決方式。再通俗深化理解下:工廠模式針對的是一個產品等級結構 ,抽象工廠模式針對的是面向多個產品等級結構的。

抽象工廠關鍵在於產品之間的抽象關係,所以一般至少要兩個產品;工廠方法在於生成產品,不關註產品間的關係,所以可以只生成一個產品。

抽象工廠更像一個複雜版本的策略模式,策略模式通過更換策略來改變處理方式或者結果;而抽象工廠的客戶端,通過更換工廠而改變結果。

工廠方法目的是生產產品,所以能看到產品,而且還要使用產品。當然,如果產品在創建者內部使用,那麼工廠方法就是為了完善創建者,從而可以使用創建者。另外創建者本身是不能更換所生產產品的。

抽象工廠的工廠是類;工廠方法的工廠是方法。抽象工廠的工廠類就做一件事情生產產品。生產的產品給客戶端使用,絕不給自己用。工廠方法生產產品,可以給系統用,可以給客戶端用,也可以自己這個類使用。自己這個類除了這個工廠方法外,還可以有其他功能性的方法。

選擇的優化

簡單工廠因為選擇是在工廠內部的,不符合開閉原則,抽象工廠和工廠方法是將選擇權交給客戶端,由客戶端根據需要自己決定要實例化的工廠。
在實際應用的時候大部分情況是只會使用一種工廠,這種情況我們一般可以藉助反射+配置來優化選擇,如果使用依賴註入,可以直接註入需要的服務即可。

使用反射+配置優化

private static readonly string AssemblyName = "AbstractFactoryPattern";
private static readonly string DbName = ConfigurationHelper.AppSetting("DbName");

public static IUserRepo CreateUserRepo()
{
    return (IUserRepo)typeof(DataAccess).Assembly.CreateInstance($"{AssemblyName}.{DbName}UserRepo");
}

public static IDepartmentRepo CreateDepartmentRepo()
{
    return (IDepartmentRepo)typeof(DataAccess).Assembly.CreateInstance($"{AssemblyName}.{DbName}DepartmentRepo");
}

使用依賴註入

依賴註入可以使得我們的代碼變得更加良好,擴展性更強。

// 依賴註入
var builder = new ContainerBuilder();
builder.RegisterType<VolunteerFactory>().As<ILeifengFactory>();
builder.RegisterType<SqlServerFactory>().As<IDbFactory>();
var container = builder.Build();

var leifengFactory = container.Resolve<ILeifengFactory>();
var volunteer = leifengFactory.CreateLeifeng();
volunteer.Wash();

var dbFactory = container.Resolve<IDbFactory>();
dbFactory.CreateDepartmentRepo().CreateDepartment(null);

Reference


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

-Advertisement-
Play Games
更多相關文章
  • 本文源碼:GitHub·點這裡 || GitEE·點這裡 一、JTA組件簡介 1、JTA基本概念 JTA即Java-Transaction-API,JTA允許應用程式執行分散式事務處理,即在兩個或多個網路電腦資源上訪問並且更新數據。JDBC驅動程式對JTA的支持極大地增強了數據訪問能力。 XA協議 ...
  • 通道 Coroutine\Channel 使用本地記憶體,不同的進程之間記憶體是隔離的。 只能在同一進程的不同協程內進行 push 和 pop 操作。 Co::set(['hook_flags'=> SWOOLE_HOOK_ALL]); Co\run(function(){ // 設置一個容量為1的通道 ...
  • 本文總結了Java集合容器的經典面試題,所有題目我都給出了自己思考,適合面試前複習掃盲使用。我不能保證裡面包含了所有集合面試題,但只要認真深挖好每一道題,做到觸類旁通,就能以不變應萬變。 大綱: 概述型面試題 List Map 小結 概述類面試題 1. 請說一下Java容器集合的分類,各自的繼承結構 ...
  • 介紹 在JDK1.5以後,我們可以使用agent技術構建一個獨立於應用程式的代理程式(即為Agent),用來協助監測、運行甚至替換其他JVM上的程式。使用它可以實現虛擬機級別的AOP功能。Agent分為兩種,一種是在主程式之前運行的Agent,一種是在主程式之後運行的Agent(前者的升級版,1.6 ...
  • 同步和非同步,阻塞和非阻塞是大家經常會聽到的概念,但是它們是從不同維度來描述一件事情,常常很容易混為一談。 ##1. 同步和非同步 同步和非同步描述的是消息通信的機制。 ###同步 當一個request發送出去以後,會得到一個response,這整個過程就是一個同步調用的過程。哪怕response為空,或 ...
  • 在WinForm程式中,實現TextBox文本輸入框占位符的方式也很多,最常用的是方式基於Windows Api SendMessage函數發送EM_SETCUEBANNER消息,或者通過TextBox自帶的焦點事件處理。 ###SendMessage函數實現 創建一個繼承TextBox的ZhmTe ...
  • 本系列將和大家分享面向對象23種設計模式中常用的幾種設計模式,本章主要簡單介紹下創建型設計模式。 ...
  • 隨著markdown格式筆記的流行,現在很多程式員都開始使用markdown來編輯自己的博客.然而,博客園的markdown格式編輯器使用體驗真的一言難盡.不過幸好,在網上找到某個大神分享的VSCode擴展,這個擴展支持VSCode本地編寫博客並直接在博客園上保存博客草稿,非常的方便. ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...