工廠方法模式(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
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...