工廠方法模式(Factory Method Pattern)

来源:https://www.cnblogs.com/ygsworld/archive/2019/04/07/10666026.html
-Advertisement-
Play Games

工廠方法模式概述 工廠方法模式是為了彌補簡單工廠模式的不足並且繼承它的優點而延生出的一種設計模式,屬於GoF中的一種。它能更好的符合開閉原則的要求。 舉個例子:大眾汽車公司想必大家都不陌生,它旗下也有不少汽車品牌。大眾汽車公司就好比一個汽車工廠,負責生產和銷售汽車。它可以為客戶提供一個客戶需要的汽車 ...


  • 工廠方法模式概述

工廠方法模式是為了彌補簡單工廠模式的不足並且繼承它的優點而延生出的一種設計模式,屬於GoF中的一種。它能更好的符合開閉原則的要求。


 

舉個例子:大眾汽車公司想必大家都不陌生,它旗下也有不少汽車品牌。大眾汽車公司就好比一個汽車工廠,負責生產和銷售汽車。它可以為客戶提供一個客戶需要的汽車。但是,如果客戶需要的汽車大眾公司目前還沒有,但是公司想要盈利,就必須為此而設計汽車,在這種情況下,大眾公司就要新添加一種汽車,同時要修改公司內部的生產環境(也就是工廠類的代碼)。這就是簡單工廠模式的運行情況。簡單而言,就是工廠類(汽車公司)什麼都要乾,要修改必須大動干戈。因而一定程度上違背了開閉原則。而工廠方法模式則不一樣,大眾汽車公司不在總公司生產汽車,而是成立分公司,收購別的公司,成立具有針對性的汽車工廠專門生產對應的汽車。若客戶的大量需求得不到滿足,則總公司就另外成立新的二級公司(新品牌汽車的工廠)生產汽車,從而在不修改具體工廠的情況下引進新的產品。正如大眾集團的收購一樣。以下為簡單工廠模式工廠方法模式的區別:

 

  • 工廠方法模式的結構與實現

 

結構:

  1. Product(抽象產品):定義產品的介面,是工廠方法模式所創建對象的公共父類(生產汽車)
  2. ConcreteProduct(具體產品):實現了抽象產品的介面,某類型的具體產品由專門的工廠創建(如具體類型的汽車)
  3. Factory(抽象工廠):它聲明瞭工廠方法,用於返回一個產品。工廠方法模式的核心,所有創建對象的工廠必須實現該介面(創建生產汽車的工廠)
  4. ConcreteFactory(具體工廠):抽象工廠類的子類,實現了抽象工廠中聲明的工廠方法,返回一個具體產品類的實例(對應具體的某一個汽車工廠)

實現(日誌記錄器)

實現:

 1 //Logger.cs  日誌記錄器介面 充當抽象產品介面
 2 namespace FactoryMethodSample
 3 {
 4     interface Logger
 5     {
 6         void WriteLog();//抽象產品方法
 7     }
 8 }
 9 
10 //DatabaseLogger 資料庫日誌記錄器 具體產品
11 namespace FactoryMethodSample
12 {
13     class DatabaseLogger : Logger
14     {
15         public void WriteLog()
16         {
17         //資料庫日誌記錄
18         }
19     }
20 } 
21 
22 //FileLogger 文件日誌記錄器 具體產品
23 namespace FactoryMethodSample
24 {
25     class FileLogger : Logger
26     {
27         public void WriteLog()
28         {
29             //文件日誌記錄
30         }
31     }
32 }
33 
34 //日誌記錄器工廠介面,充當抽象工廠
35 namespace FactoryMethodSample
36 {
37     interface LoggerFactory
38     {
39         Logger CreateLogger();//抽象工廠方法
40     }
41 }
42 //DatabaseLoggerFactory 資料庫日誌記錄器工廠類,具體工廠
43 namespace FactoryMethodSample
44 {
45     class DatabaseLoggerFactory : LoggerFactory
46     {
47         public Logger CreateLogger()
48         {
49             //連接資料庫
50             //創建記錄器對象
51             Logger logger = new DatabaseLogger();
52             ...
53             return logger;
54         }
55     }
56 }
57 //FileLoggerFactory 文件日誌記錄器工廠類,具體工廠
58 namespace FactoryMethodSample
59 {
60     class FileLoggerFactory : LoggerFactory
61     {
62         public Logger CreateLogger()
63         {
64             //創建文件日誌記錄器
65             Logger logger = new FileLogger();
66             ...
67             return logger;
68         }
69     }
70 }
71 //Program 客戶端測試
72 namespace FactoryMethodSample
73 {
74     class Program
75     {
76         
77         static void Main(string [] args)
78         {
79             LoggerFactory factory;//抽象工廠
80             Logger logger;//抽象產品
81             factory = new FileLoggerFactory();//new DatabaseLoggerFactory 可以更換為資料庫日誌記錄器
82             logger = factory.CreateLogger();//抽象工廠方法
83             logger.WriteLog();//抽象產品方法
84             ....
85         }
86         //如果要添加新的日誌記錄器,只要增加新的具體工廠類,併在客戶端中修改具體工廠的類名便可以,從而避免了對原類的修改
87     }
88 }
  • 工廠方法模式的重載

 在某種情況下,可以用不同的方式來初始化一個產品類,在Logger記錄器中,連接資料庫的操作可以不用在每次CreateLog後再傳入。而是可以將相關參數封裝在一個object中,通過object對象將參數傳入工廠類中,或者在參數列表中給出連接方式來連接資料庫。為此,可以提供一組重載的工廠方法,以不同的方式創建產品。

 

 代碼修改如下:

 1 namespace FactoryMethodSample
 2 {
 3     interface LoggerFactory
 4     {
 5         Logger CreateLogger();//抽象工廠方法
 6         Logger CreateLogger(string args);
 7         Logger CreateLogger(object obj);
 8     }
 9 }
10 
11 //DatabaseLoggerFactory 資料庫日誌記錄器工廠類,具體工廠
12 namespace FactoryMethodSample
13 {
14     class DatabaseLoggerFactory : LoggerFactory
15     {
16         public Logger CreateLogger()
17         {
18             //連接資料庫
19             //創建記錄器對象
20             Logger logger = new DatabaseLogger();
21             ...
22             return logger;
23         }
24     }
25     
26     class DatabaseLoggerFactory : LoggerFactory
27     {
28         public Logger CreateLogger(string args)
29         {
30             //用args連接資料庫
31             //
32             Logger logger = new DatabaseLogger();
33             ...
34             return logger;
35         }
36     }
37     
38     class DatabaseLoggerFactory : LoggerFactory
39     {
40         public Logger CreateLogger(object obj)
41         {
42             //將參數封裝在obj中來連接資料庫
43             Logger logger = new DatabaseLogger();
44             ...
45             return logger;
46         }
47     }
48 }
  • 工廠方法模式的隱藏

 在客戶端中,為簡化使用,可以隱藏工廠方法。在工廠類調直接調用產品類的方法,在客戶端中無需用工廠方法創建產品對象,直接使用工廠對象即可調用所創建的產品對象中的業務方法

代碼修改如下:

 1 //LoggerFactory 修改
 2 abstract class LoggerFactory//改介面為抽象類
 3 {
 4     public void WriteLog()//工廠類直接調用日誌記錄器的WriteLog();
 5     {
 6         Logger logger = this.CreateLogger();
 7         logger.WriteLog();
 8     }
 9     public abstract Logger CreateLogger();
10 }
11 
12 //客戶端修改如下
13 namespace FactoryMethodSample
14 {
15     class Program
16     {
17         static void Main(string [] args)
18         {
19             LoggerFactory factory;
20             //Load configuration file;
21             string factoryString = ConfigurationManager.AppSettings["factory"];
22             //反射生成對象
23             factory = (LoggerFactory)Assembly.Load("FactoryMethodSample").CreateInstance(factoryString);
24             factory.WriteLog();//直接使用工廠對象調用產品對象的業務方法
25         }
26     }
27 }

 

  • 工廠方法模式的優缺點和適用環境

  (1)工廠方法模式的優點

    (1)用戶只需要關心產品對應的工廠,甚至無需關心創建細節或具體產品類的類名  
    (2)基於工廠角色和產品的多態性設計是工廠模式的關鍵。它能自主決定如何創建哪種產品對象,而創建細節都封裝在具體工廠內部
    (3)在系統要添加新的產品時,無需修改抽象工廠和抽象產品提供的介面,無需修改客戶端,也無需修改其他的具體工廠和具體產品,只要添加一個具體工廠和具體產品即可,從而提高系統的可擴展性(符合開閉原則)  

  (2)工廠方法模式的缺點

    (1)在添加新產品時,要編寫新的具體產品類,並要提供與之對應的具體工廠類。系統軟體個數也成對增加,從而增加了系統的複雜度,帶來更多開銷
    (2)由於系統的可擴展性,在客戶端中要引入抽象層進行定義,從而增加了系統的抽象性和理解難度

  (3)工廠方法模式的適用環境

    (1)客戶端不需要知道它需要的對象的類。只需知道對應的工廠即可

    (2)抽象工廠類通過子類來指定創建那哪個對象。即抽象工廠類只需要提供一個創建產品的介面,而由其子類確定具體要創建的對象,利用多態性和里氏代換原則,子類對象將覆蓋父類對象,從而使系統更容易擴展 


 

  •  在日誌記錄器實例中,在更換日誌記錄器時需要修改客戶端代碼。為了按照開閉原則的要求執行,可以在不修改任何客戶端代碼的基礎上更換或增加新的日誌記錄方式。即通過配置文件程式集的反射機制,讀取配置文件中存儲的類名字元串生成對象。這裡沒有進行講解,可以自行搜索..~_~!!

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

-Advertisement-
Play Games
更多相關文章
  • 實現輸入內容點擊請留言按鈕,就會在下方留言並且後面有刪除選項,點擊即可刪除留言。 ...
  • 測試代碼: ...
  • 實例代碼: 同理可應用在超鏈接、按鈕等中 ...
  • typeof操作符返回一個字元串,表示未經計算的操作數的類型。 可能返回值有:"undefined"、"object"、"boolean"、"number"、"string"、"symbol"、"function"、"object" 例: instanceof運算符用於測試構造函數的prototyp ...
  • 變數作用域: 1、一個變數的作用域是程式源代碼中定義這個變數的區域 2、在函數內聲明的變數是局部變數,它只在該函數及其嵌套作用域里可見(js 函數可嵌套定義);不在任何函數內聲明或在函數內不使用 var 或 let 關鍵字聲明的變數是全局變數,它在整個 JavaScript 程式里都可見 3、Jav ...
  • 為什麼JavaScript是單線程? JavaScript的一大特點就是單線程, 同一時間只能做一件事情,主要和它的用途有關, JavaScript主要是控制和用戶的交互以及操作DOM。註定它是單線程。 假如是多個線程, 一個移除DOM節點,一個新增DOM節點,瀏覽器以誰的為準呢? 什麼是執執行棧呢 ...
  • 前提 vue在前端技術中使用越來越多,也成為了主流框架,花點時間稍微瞭解下vue-cli、vue-router結合element-ui的使用。本人使用的是windows系統,後續介紹以windows7系統為例。 1.安裝vue-cli 首先保證自己電腦上已經安裝過nodejs,是否安裝打開cmd,輸 ...
  • 本文將介紹如何使用Docker Compose搭建Istio。Istio號稱支持多種平臺(不僅僅Kubernetes)。然而,官網上非基於Kubernetes的教程仿佛不是親兒子,寫得非常隨便,不僅缺了一些內容,而且還有坑。本文希望能補實這些內容。我認為在學習Istio的過程中,相比於Kuberne ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...