主頁 > 軟體設計 > 設計模式之工廠模式

設計模式之工廠模式

2020-09-12 00:27:59 軟體設計

工廠模式-------簡單工廠模式,工廠方法模式、抽象工廠模式

簡單工廠模式、工廠方法模式、抽象工廠模式,都是屬于創建型設計模式,嚴格上來說,簡單工廠模式不屬于23設計模式之一,因為它違背了開閉原則,

這三種設計模式,名字都包含“工廠”二字,如果沒有認真地對它們的設計思想、代碼進行認真比較,還真的很難區分出究竟是哪一種模式,很多開發者很容易混淆,

接下來,我就將這三種設計模式放在一篇文章,用C#來實作它們并放在一起進行比較,

 

一、簡單工廠模式

想象一下,現在商場有很多賣不同口味的冰激凌攤位,每個攤位的位置都不盡相同,每個商家只賣一種口味,商家提供了制作冰激凌的所有原料,需要顧客自己去制作,這時,同伴三個人,你說你去買冰激凌,讓大家說說都想買什么口味的冰激凌,最后三個人剛好喜歡的口味都不同,分別是蘋果味、香蕉味、橘子味,大家委托你去買,你就跑到了A攤位,自己調制起了一根(一個?)蘋果味的冰激凌,然后,你又跑到幾十米外另一攤位去制作香蕉味冰激凌,最后又跑到另一攤位去制作橘子味的冰激凌,終于買好了三根冰激凌,拿回去后,發現自己那杯蘋果味的已經融化了…如果,你們一行有十幾個人,每個人需要的口味都不同呢?這樣是不是很麻煩?

商場管理人員意識到了這個問題,想了一個方法,他將所有的口味的冰激凌攤位,全部集中到了商場入口處來賣,并且,訂購了一臺賣冰激凌的機器,機器上有一排按鈕,每個按鈕代表一種口味的冰激凌,你想買哪一種口味就點擊哪個按鈕,機器內部就會自己去制作一根該口味的冰激凌,然后吐出該冰激凌給顧客,可以發現,顧客只需按一個按鈕,根本不需要像之前那樣自己去制作冰激凌,機器制作冰激凌的程序對于顧客來說也是透明的,這種模式,就是我們的 簡單工廠模式 ,而生產冰激凌的機器,就是我們所說的 工廠 ,

1. 首先定義一個冰激凌介面,里邊只有一個方法,就是顯示是哪種口味

   /// <summary>
    /// 冰激凌介面
    /// </summary>
    public interface IceCream
    {
        void Taste();
    }

2.定義三個類,AppleIceCream、BananaIceCream、OrangeIceCream,并繼承上面的介面,實作其中的方法,顯示自己獨特的口味

/// <summary>
/// 蘋果
/// </summary>
public class AppleIceCream : IceCream
{
    public void Taste()
    {
        Console.WriteLine("這是蘋果口味的冰激凌");
    }
}
/// <summary>
/// 香蕉
/// </summary>
public class BananaIceCream : IceCream
{
    public void Taste()
    {
        Console.WriteLine("這是香蕉口味的冰激凌");
    }
}
/// <summary>
/// 橘子
/// </summary>
public class OrangeIceCream : IceCream
{
    public void Taste()
    {
        Console.WriteLine("這是橘子口味的冰激凌");
    }
}

 3.定義一個工廠類,用來制作不同口味的冰激凌

 /// <summary>
 /// 工廠(制作冰淇淋的機器)
 /// </summary>
 public class IceCreamFactory
 {
     public static IceCream creamIceCream(string taste)
     {
         IceCream iceCream = null;
         // 這里我們通過switch來判斷,具體制作哪一種口味的冰激凌
         switch (taste)
         {
             case "Apple":
                 iceCream = new AppleIceCream();
                 break;

             case "Orange":
                 iceCream = new OrangeIceCream();
                 break;

             case "Banana":
                 iceCream = new BananaIceCream();
                 break;
             default:
                 break;
         }
         return iceCream;
     }
 }

4.最后看一下客戶端的代碼

 static void Main(string[] args)
 {
     IceCream appleIceCream = IceCreamFactory.creamIceCream("Apple");
     appleIceCream.Taste();//這是蘋果口味的冰激凌
IceCream bananaIceCream = IceCreamFactory.creamIceCream("Banana"); bananaIceCream.Taste();//這是香蕉口味的冰激凌
IceCream orangeIceCream = IceCreamFactory.creamIceCream("Orange"); orangeIceCream.Taste();//這是橘子口味的冰激凌
Console.ReadKey(); }

運行結果如下:

可以看到,簡單工廠模式確實很“簡單”,一般,簡單工廠方法模式中,工廠類中有一個方法,通過switch中不同的值或者if else陳述句來創建不同的物件并回傳,通常這個方法是一個靜態方法,(順便一提:簡單工廠模式也被稱作“靜態工廠模式”)在客戶端直接呼叫工廠類的該方法就可以,整個冰激凌的生產(創建不同口味冰激凌的程序)被這個工廠類封裝了,客戶端不用去關注這些細節,

 

二、工廠方法模式

用了簡單方法模式后,顧客們方便多了,想要哪種口味的冰激凌就直接點一下按鈕即可直接購買,現在,該機器只能賣三種口味的冰激凌,并沒有滿足很多顧客的需求,管理員打算再添加一種草莓味的冰激凌來滿足更多顧客,問題來了,整個機器已經做成了,按鈕數目為3也已經固定了,如果想要再添加一種口味,那么就要打開機器內部,往里邊添加制作草莓味冰激凌的原料以及制作工藝,還要在機器外部再增加一個按鈕,這可麻煩了,畢竟整個機器的布局什么的都固定下來了,

其實,這正是簡單工廠模式的缺點,其違背了開閉原則,擴展性差,觀察簡單工廠模式的工廠類代碼,我們可以發現,其內部做了很多邏輯的處理,通過switch值的不同來創建不同的物件,現在,如果要新增草莓味的冰激凌,首先要新增StrawberryIceCream,并且,還要在switch里邊,新增一個case分支,來判斷是否生產StrawberryIceCream,所以不是很合理,

通過 工廠方法模式 ,我們就能解決這一問題,仔細研究,之所以會產生上面的問題,是因為我們只有一個“工廠”,無論何種口味的冰激凌生產,都交給這個工廠去處理導致的,那么,現在,我們可以,設計多個“工廠”,每種工廠只負責生產一種口味的冰激凌,回到商場來,還是在商場入場處,我們購置多臺生產冰激凌的機器,每臺機器只能生產一種口味的冰激凌,每臺機器有一個按鈕,點擊下去就會吐出該口味冰激凌,然后將這些機器一個挨著一個排列起來就行,現在,如果要添加一種新的口味,那么只要再購置一臺機器,然后挨著放進去即可,

 

 

 接下來,看看具體的代碼實作: 
1. 和簡單工廠模式一樣,先定義一個介面,再定義AppleIceCreamBananaIceCreamOrangeIceCream去實作這個介面(看上面1和2步驟)

2.定義工廠介面

/// <summary>
/// 工廠模式介面
/// </summary>
public interface IceCreamFactory
{
    IceCream CreateIceCream();
}

 

3.再分別定義AppleIceCreamFactory、BananaIceCreamFactory、OrangeIceCreamFactory,繼承剛剛定義的工廠介面

/// <summary>
/// 蘋果工廠
/// </summary>
public class AppleIceCreamFactory : IceCreamFactory
{
    public IceCream CreateIceCream()
    {
        return new AppleIceCream();
    }
}
/// <summary>
/// 香蕉工廠
/// </summary>
public class BananaIceCreamFactory : IceCreamFactory
{
    public IceCream CreateIceCream()
    {
        return new BananaIceCream();
    }
}
/// <summary>
/// 橘子工廠
/// </summary>
public class OrangeIceCreamFactory : IceCreamFactory
{
    public IceCream CreateIceCream()
    {
        return new OrangeIceCream();
    }
}

4.客戶端代碼

static void Main(string[] args)
{ //生產蘋果味冰激凌
    IceCreamFactory appleFactory = new AppleIceCreamFactory();
    IceCream appleIceCream = appleFactory.CreateIceCream();
    appleIceCream.Taste();

    //生產香蕉口味冰激凌
    IceCreamFactory bananaFactory = new BananaIceCreamFactory();
    IceCream bananaIceCream = bananaFactory.CreateIceCream();
    bananaIceCream.Taste();

    //生產橘子口味冰激凌
    IceCream orangeIceCream = new OrangeIceCreamFactory().CreateIceCream();
    orangeIceCream.Taste();
Console.ReadKey(); }
運行結果如下

 

三、抽象工廠模式

 

可以想象,不同人的需求是不同的,有的人吃冰激凌是當做飯后甜點,有的人直接把它當飯吃,因此,商場為了讓顧客有多種選擇,想要對每種口味冰激凌的量進行分類,分為大份和小份的,比如我們之前生產的是大份的冰激凌,那么要完成生產多種口味小份的冰激凌,能怎么做呢?當然,商場可以再購置蘋果味冰激凌(小份)、香蕉味冰激凌(小份)、橘子味冰激凌(小份)的機器,然后挨著放在之前幾臺旁邊,這種思路就是我們上邊的工廠方法模式,可是,這樣就需要添加多了一倍的機器數量,想象一下,如果商場在一開始規劃的時候就已經打算賣兩種分量多種口味的冰激凌,那能怎么做呢?

由于每種口味的冰激凌,材料和制作工藝都是相同的,所以,我們完全可以,每臺機器負責生產特定口味的冰激凌,并配備兩個按鈕,用來區分生產大份的或者是小份的,這樣是比較符合現實的,這就是我們接下來要說的 抽象工廠模式,

 

 

1. 由于要生產不同大小的冰激凌,所以,現在冰激凌的介面有兩個,分別是 BigIceCream 和 SmallIceCream

public interface BigIceCream
{
    void Taste();
}

public interface SmallIceCream
{
    void Taste();
}

 2.定義各個口味的冰激凌,繼承剛剛定義的介面,實作其方法

public class BigAppleIceCream : BigIceCream
{
    public void Taste()
    {
        Console.WriteLine("這是蘋果味冰激凌(大份)");
    }
}
public class SmallAppleIceCream : SmallIceCream
{
    public void Taste()
    {
        Console.WriteLine("這是蘋果味冰激凌(小份)");
    }
}
//后邊還有四個類BigBananaIceCream、SmallBananaIceCream、BigOrangeIceCream、SmallOrangeIceCream

3.定義工廠介面,可以看到,這里有兩個方法,分別生產小份大的和大份的

/// <summary>
/// 生產小份大的和大份的介面
/// </summary>
public interface IceCreamFactory
{
    BigIceCream CreateBigIceCream();

    SmallIceCream CreateSmallIceCream();
}

 

4.定義三個工廠類繼承上邊的介面并實作其方法

public class AppleIceCreamFactory : IceCreamFactory
{
    public BigIceCream CreateBigIceCream()
    {
        return new BigAppleIceCream();
    }
    public SmallIceCream CreateSmallIceCream()
    {
        return new SmallAppleIceCream();
    }
}
//這里是蘋果味的大份和小份,香蕉和橘子按同樣的方法添加

 5.客戶端代碼

/// <summary>
/// 抽象工廠模式
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
    //生產蘋果味冰激凌
    IceCreamFactory appleIceCreamFactory = new AppleIceCreamFactory();
    BigIceCream appleBigIceCream = appleIceCreamFactory.CreateBigIceCream();
    SmallIceCream appleSmallIceCream = appleIceCreamFactory.CreateSmallIceCream();
    appleBigIceCream.Taste();
    appleSmallIceCream.Taste();
    Console.ReadKey();
}
運行結果如下

 

可以看到,之所以叫抽象工廠,是因為和工廠方法相比,這里有多個抽象產品類存在(即大份的冰激凌和小份的冰激凌),每個抽象產品類可以派生出多個具體的產品,生產的是系列產品,其工廠介面相對于工廠方法模式而言,是有多個方法的,用來生產不同的抽象產品,

不過,我們也很容易看出,抽象工廠模式的弊端,比如現在,商場想要提供的是大、中、小三種系列產品,那么現在,需要改動的代碼就有點多了,首先需要創建一個介面,用來生產中份的冰激凌,然后還要實作具體的類,還需要修改工廠介面,并修改具體的工廠類,

四、總結

通過UML圖以及代碼不難對三種工廠模式進行一個區分,簡單工廠模式,工廠類是整個模式的關鍵所在,包含了必要的邏輯判斷,能夠外界給定的資訊, 決定究竟創建哪個具體類的物件,工廠方法模式 是對簡單工廠方法模式的一個抽象,抽離出了一個Factory類(或者介面),這個介面不負責具體產品的生產,而只是指定一些規范,具體的生產作業由其子類去完成,這個模式中,工廠類和產品類往往是一一對應的,完全解決了簡單工廠模式中違背“開閉原則”的問題,實作了可擴展;抽象工廠模式 的特點是存在多個抽象產品類,每個抽象產品類可以派生出多個具體產品類,工廠提供多種方法,去生產“系列”產品,

簡單工廠模式適用于工廠類需要創建的物件比較少的情況,客戶只需要傳入具體的引數,就可以忽略工廠的生產細節,去獲取想要的物件;

工廠方法模式,主要是針對單一產品結構的情景;

抽象工廠模式則是針對多級產品結構(系列產品)的一種工廠模式,

最后在說一下,每種模式都有自己的優點和弊端,沒有最好的模式,只有最適合的模式,只要符合實際開發需求就是最好的,


原文鏈接:https://blog.csdn.net/weixin_35985385/article/details/81430545

原文是用java實作的,我這里是用C#實作的

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/8589.html

標籤:設計模式

上一篇:設計模式:程式員跳不開的坑

下一篇:軟體設計模式修煉 -- 中介者模式

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more