設計模式-創建型-工廠模式

来源:https://www.cnblogs.com/az4215/archive/2019/09/13/11516734.html
-Advertisement-
Play Games

工廠設計模式: 顧名思義,該模式是用來生產對象的。在面向對象的設計模式中,萬物皆對象,若使用new來創建對象,就會對該對象產生強耦合,加入我們需要更換該對象,那麼使用該對象的對象都需要進行修改,這顯然違背了開閉原則(OCP)。如果我們使用工廠來產生對象,我們只需要與這個工廠打交道就可以了,無需關心具 ...


工廠設計模式:

  顧名思義,該模式是用來生產對象的。在面向對象的設計模式中,萬物皆對象,若使用new來創建對象,就會對該對象產生強耦合,加入我們需要更換該對象,那麼使用該對象的對象都需要進行修改,這顯然違背了開閉原則(OCP)。如果我們使用工廠來產生對象,我們只需要與這個工廠打交道就可以了,無需關心具體的對象,達到解耦的目的。

  接下來我們從實際的案例出發,從無工廠到有工廠的區別。

  去披薩店訂購披薩,首先披薩的種類很多(CheesePizza、GreekPizza、DurianPizza{等),披薩的製作流程有prepare、bake、cut、box。

傳統模式:

   

 1 internal class Program
 2 {
 3     private static void Main(string[] args)
 4     {
 5         new OrderPizza();
 6     }
 7 }
 8 
 9 internal class OrderPizza
10 {
11     public OrderPizza()
12     {
13         Pizza pizza = null;
14         string orderType = "";
15         do
16         {
17             orderType = Console.ReadLine();
18             if (orderType == "cheese")
19             {
20                 pizza = new CheesePizza();
21                 pizza.setName("芝士披薩");
22             }
23             else if (orderType == "greek")
24             {
25                 pizza = new GreekPizza();
26                 pizza.setName("希臘披薩");
27             }
28             else
29             {
30                 Console.WriteLine("訂購失敗");
31                 break;
32             }
33             //開始製作
34             pizza.prepare();
35             pizza.bake();
36             pizza.cut();
37             pizza.box();
38         } while (true);
39     }
40 }
41 
42 internal abstract class Pizza
43 {
44     private string name;
45 
46     public abstract void prepare();
47 
48     public void bake()
49     {
50         Console.WriteLine($"{this.name} 烘培");
51     }
52 
53     public void cut()
54     {
55         Console.WriteLine($"{this.name} 修剪");
56     }
57 
58     public void box()
59     {
60         Console.WriteLine($"{this.name} 打包");
61     }
62 
63     public void setName(string name)
64     {
65         this.name = name;
66     }
67 }
68 
69 internal class CheesePizza : Pizza
70 {
71     public override void prepare()
72     {
73         Console.WriteLine("芝士披薩準備中");
74     }
75 }
76 
77 internal class GreekPizza : Pizza
78 {
79     public override void prepare()
80     {
81         Console.WriteLine("希臘披薩準備中");
82     }
83 }
view code

  傳統模式的優缺點:

    1、比較好理解,易於操作

    2、違反OCP原則,即對擴展開放,對修改關閉。

    3、這裡只訂購了兩種pizza,若現在又新增了品種DurianPizza,這個時候就需要添加該類以及修改OrderPizza中的代碼。從上圖中可以看出,OrderPizza依賴抽象類及具體實現類的,那怎樣才能切斷OrderPizza與類之間的依賴關係呢。於是我們想到,可以定義一個工廠,訂購者不需要知道具體pizza的製作流程,只要直到我需要訂購什麼類型的pizza就行了。

 

簡單工廠模式:

   

  1 internal class Program
  2 {
  3     private static void Main(string[] args)
  4     {
  5         new OrderPizza();
  6     }
  7 }
  8 
  9 internal class OrderPizza
 10 {
 11     public OrderPizza()
 12     {
 13         Pizza pizza = null;
 14         string orderType = "";
 15         do
 16         {
 17             Console.Write("請輸入訂購類型:");
 18             orderType = Console.ReadLine();
 19             pizza = SimpleFactory.createPizza(orderType);
 20             if (pizza == null)
 21             {
 22                 Console.WriteLine("訂購失敗");
 23                 break;
 24             }
 25             //開始製作
 26             pizza.prepare();
 27             pizza.bake();
 28             pizza.cut();
 29             pizza.box();
 30         } while (true);
 31     }
 32 }
 33 
 34 internal static class SimpleFactory
 35 {
 36     public static Pizza createPizza(string orderType)
 37     {
 38         Pizza pizza = null;
 39         do
 40         {
 41             if (orderType == "cheese")
 42             {
 43                 pizza = new CheesePizza();
 44                 pizza.setName("芝士披薩");
 45             }
 46             else if (orderType == "greek")
 47             {
 48                 pizza = new GreekPizza();
 49                 pizza.setName("希臘披薩");
 50             }
 51             else if (orderType == "durian")
 52             {
 53                 pizza = new DurianPizza();
 54                 pizza.setName("榴蓮披薩");
 55             }
 56             return pizza;
 57         } while (true);
 58     }
 59 }
 60 
 61 internal abstract class Pizza
 62 {
 63     private string name;
 64 
 65     public abstract void prepare();
 66 
 67     public void bake()
 68     {
 69         Console.WriteLine($"{this.name} 烘培");
 70     }
 71 
 72     public void cut()
 73     {
 74         Console.WriteLine($"{this.name} 修剪");
 75     }
 76 
 77     public void box()
 78     {
 79         Console.WriteLine($"{this.name} 打包");
 80     }
 81 
 82     public void setName(string name)
 83     {
 84         this.name = name;
 85     }
 86 }
 87 
 88 internal class CheesePizza : Pizza
 89 {
 90     public override void prepare()
 91     {
 92         Console.WriteLine("芝士披薩準備中");
 93     }
 94 }
 95 
 96 internal class GreekPizza : Pizza
 97 {
 98     public override void prepare()
 99     {
100         Console.WriteLine("希臘披薩準備中");
101     }
102 }
103 
104 internal class DurianPizza : Pizza
105 {
106     public override void prepare()
107     {
108         Console.WriteLine("榴蓮披薩準備中");
109     }
110 }
view code

  簡單工廠模式優缺點:

    1、由代碼可以看出,雖然簡單工廠模式一定程度上減少了因需求變更而導致的代碼更改,但是實際仍違背了OCP原則。

    2、所以簡單工廠模式只適合產品對象相對較少,且產品固定的需求,對產品變化無常的需求來說顯然不適合。

 

工廠方法設計模式:

  披薩項目需求變更,客戶點披薩時可以點不同口味的披薩。 

   

  1 internal class Program
  2 {
  3     private static void Main(string[] args)
  4     {
  5         new BJOrderPizza();
  6     }
  7 }
  8 
  9 internal abstract class OrderPizza
 10 {
 11     public OrderPizza()
 12     {
 13         Pizza pizza = null;
 14         string orderType = "";
 15         do
 16         {
 17             Console.Write("請輸入訂購類型:");
 18             orderType = Console.ReadLine();
 19             pizza = createPizza(orderType);
 20             if (pizza == null)
 21             {
 22                 Console.WriteLine("訂購失敗");
 23                 break;
 24             }
 25             //開始製作
 26             pizza.prepare();
 27             pizza.bake();
 28             pizza.cut();
 29             pizza.box();
 30         } while (true);
 31     }
 32 
 33     public abstract Pizza createPizza(string orderType);
 34 }
 35 
 36 internal class BJOrderPizza : OrderPizza
 37 {
 38     public override Pizza createPizza(string orderType)
 39     {
 40         Pizza pizza = null;
 41         if (orderType == "cheese")
 42         {
 43             pizza = new BJCheesePizza();
 44         }
 45         else if (orderType == "greek")
 46         {
 47             pizza = new BJGreekPizza();
 48         }
 49         return pizza;
 50     }
 51 }
 52 
 53 internal class LDOrderPizza : OrderPizza
 54 {
 55     public override Pizza createPizza(string orderType)
 56     {
 57         Pizza pizza = null;
 58         if (orderType == "cheese")
 59         {
 60             pizza = new LDCheesePizza();
 61         }
 62         else if (orderType == "greek")
 63         {
 64             pizza = new LDGreekPizza();
 65         }
 66         return pizza;
 67     }
 68 }
 69 
 70 internal abstract class Pizza
 71 {
 72     private string name;
 73 
 74     public abstract void prepare();
 75 
 76     public void bake()
 77     {
 78         Console.WriteLine($"{this.name} 烘培");
 79     }
 80 
 81     public void cut()
 82     {
 83         Console.WriteLine($"{this.name} 修剪");
 84     }
 85 
 86     public void box()
 87     {
 88         Console.WriteLine($"{this.name} 打包");
 89     }
 90 
 91     public void setName(string name)
 92     {
 93         this.name = name;
 94     }
 95 }
 96 
 97 internal class BJCheesePizza : Pizza
 98 {
 99     public override void prepare()
100     {
101         Console.WriteLine("北京的芝士披薩準備中");
102     }
103 }
104 
105 internal class BJGreekPizza : Pizza
106 {
107     public override void prepare()
108     {
109         Console.WriteLine("北京的希臘披薩準備中");
110     }
111 }
112 
113 internal class LDCheesePizza : Pizza
114 {
115     public override void prepare()
116     {
117         Console.WriteLine("倫敦的芝士披薩準備中");
118     }
119 }
120 
121 internal class LDGreekPizza : Pizza
122 {
123     public override void prepare()
124     {
125         Console.WriteLine("倫敦的希臘披薩準備中");
126     }
127 }
view code

  工廠方法模式的優缺點:

    1、讓父類的實現延遲到子類中去,減少判斷。

    2、換湯不換藥,和簡單工廠模式類似,一般適用於產品對象相對較少,且產品固定的需求。

    3、工廠方法一定程度上減輕了工廠的職責,將職責細化,避免工廠類無法正常運行而導致程式崩潰。

參考:https://www.jianshu.com/p/38493eb4ffbd 


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

-Advertisement-
Play Games
更多相關文章
  • “處理指令(PIs)允許文檔包含用於應用程式的指令。指令並不是文檔字元數據的一部分,但是必須通過應用程式傳遞”。 處理指令可以用於將信息傳遞給應用程式。處理指令可以出現在文檔任意位置的標記外部。可以出現在序言中,包括文檔的類型定義(DTD),文本內容或者文檔之後。 處理指令,允許文檔中包含由應用程式 ...
  • 數據交互是前端很重要的一部分,靜態頁是基礎,而交互才是網頁的精髓。交互又分為人機交互和前後端數據交互,現階段的互聯網下,大部分的網站都要進行前後端數據交互,如何交互呢?交互的流程大概就是前端發送數據給後端,後端接送數據,進行處理,將處理後的結果發送給前端,前端接受數據。前端和後端的收和發通過什麼呢? ...
  • 結構元素不具有任何樣式,只是使頁面元素的的語義更加明確。 header元素 header元素是一種具有引導和導航作用的的結構元素, 該元素可以包含所有通常放在頁面頭部的內容 。header元素通常用來放置整個頁面或頁面內的一個內容區塊的標題,也可以包含網站Logo圖片、搜索表單或者其他相關內容。 一 ...
  • js由三部分組成,分別是ECMAScript、DOM、BOM 其中ECMAScript規定了js的語法 js是一門解釋型語言、腳本語言、動態類型語言、基於對象語言 書寫js代碼和CSS一樣,有三個書寫的地方,第一個是使用<script>標簽,再<sccript>標簽中書寫js代碼,標簽一般都在bod ...
  • 如果您的瀏覽器支持 XSLT,那麼在瀏覽器中它可被用來將文檔轉換為 XHTML。 如果您的瀏覽器支持 XSLT,那麼在瀏覽器中它可被用來將文檔轉換為 XHTML。 JavaScript 解決方案 在前面的章節,我們已向您講解如何使用 XSLT 將某個 XML 文檔轉換為 XHTML。我們是通過以下途 ...
  • 一、html語言概述 超文本標記語言(英語:HyperText Markup Language,簡稱:HTML)是一種用於創建網頁的標準標記語言。 您可以使用 HTML 來建立自己的 WEB 站點,HTML 運行在瀏覽器上,由瀏覽器來解析。 二、目前瀏覽器內核(瞭解): 三、HTML 初體驗 上述實 ...
  • ​ 路由獨立守衛,顧名思義就是這個路由自己的守衛任務,就如同咱們LOL,我們守衛的就是獨立一條路,保證我們這條路不要被敵人攻剋(當然我們也得打團配合) 在官方定義是這樣說的:你可以在路由配置上直接定義 beforeEnter 守衛,這些守衛與全局前置守衛的方法參數是一樣的。 參數如下: 我們在這裡使 ...
  • 前言: 對於大多數前端同學來說閉包一直是個很讓人困惑的問題,我自己之前雖說在項目中有意無意的用到但是都沒有刻意的去深入研究它,大部分時間是為了應付面試。後來某一天我突然意識到自己要去認真研究下它,因為知其然而不知其所以然並不應該是學習一種語言的態度,所以我打算寫篇文章嘗試著用我自己的理解去解釋下閉包 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...