設計模式(3)抽象工廠模式(Abstract Factory)

来源:http://www.cnblogs.com/fonour/archive/2017/07/25/7235605.html
-Advertisement-
Play Games

設計模式(0)簡單工廠模式 設計模式(1)單例模式(Singleton) 設計模式(2)工廠方法模式(Factory Method) 源碼地址 0 抽象工廠模式簡介 0.0 抽象工廠模式定義 抽象工廠模式一般的書面定義為:提供一個創建一系列相關或相互依賴對象的介面,而無需指定他們具體的類 提供創建接 ...


設計模式(0)簡單工廠模式

設計模式(1)單例模式(Singleton)

設計模式(2)工廠方法模式(Factory Method)

源碼地址

0 抽象工廠模式簡介

0.0 抽象工廠模式定義

抽象工廠模式一般的書面定義為:提供一個創建一系列相關或相互依賴對象的介面,而無需指定他們具體的類

提供創建介面,無需指定具體實現類,這個原則在簡單工廠模式和工廠方法模式篇已經反覆講到了,這是面向介面編程的一個基本準則,很顯然,從抽象工廠模式的一般定義中可以看出這也是抽象工廠模式的一個核心,而抽象工廠模式的另一個核心是要解決一系列相關或相依賴對象(產品族)創建的問題。這也是這幾種工廠模式的細節區別所在的關鍵點所在,初學設計模式時往往因為沒有認識到這一點區別而對幾種工廠模式難以理解

我們可以簡單的這麼理解,抽象工廠模式不單單要解決對象的創建問題,還要涉及到創建的對象之間的相互依賴或者約束關係。工廠方法模式和簡單工廠模式解決了單個產品對象創建的問題,它們只關心單個產品對象的創建,而抽象工廠模式是關註的產品族(多個相互關聯對象)的創建,最終創建的產品族形成一個新的產品對象。

抽象工廠模式的結構圖如下:

2007911165328

AbstractFactory:抽象工廠類,定義創建某個產品所需相關對象的操作介面

ProductFactory1/ProductFactory2:具體的工廠類,實現抽象工廠定義的方法,負責某個產品所需所有對象創建操作介面的具體實現。

AbstractProductA/AbstractProductB:定義某一類產品對象的介面

ProductA1/ProductA2/ProductB1/ProductB2:具體產品對象的實現

0.1 抽象工廠模式應用場景

如果對上面的文字描述還不能有一個直觀的認識,我們仍然從一個簡單的應用場景來說明抽象工廠模式的引入時機。

野外商店老闆為了更好的服務眾英雄,特將店內隱身藥水進行了一次升級,分為紅瓶裝(瓶口直徑2cm)、藍瓶裝(瓶口直徑5cm)2款,並且2種瓶子分別搭配圓形(2cm)和方形(5cm)兩種款式的瓶蓋。英雄們來到商店後,只需要將自己的的需要告訴商店老闆,老闆根據英雄的要求,去取瓶子和蓋子進行組裝即可。

在應用抽象工廠模式之前,我們很簡單的使用簡單工廠模式實現這個需求。

定義瓶子介面及實現類

/// <summary>
/// 定義瓶子介面
/// </summary>
public interface IBottle
{
    /// <summary>
    /// 展示自己的信息
    /// </summary>
    void ShowInfo();
}
/// <summary>
/// 紅色瓶子
/// </summary>
public class RedBottle : IBottle
{
    /// <summary>
    /// 展示自己的信息
    /// </summary>
    public void ShowInfo()
    {
        Console.WriteLine("我是一個熱情火辣的紅色瓶子,我的瓶口直徑是2cm。");
    }
}

定義瓶蓋介面及實現類

/// <summary>
/// 定義瓶蓋介面
/// </summary>
public interface ICap
{
    /// <summary>
    /// 展示自己的信息
    /// </summary>
    void ShowInfo();
}
/// <summary>
/// 圓形瓶蓋
/// </summary>
public class RoundCap : ICap
{
    /// <summary>
    /// 展示自己的信息
    /// </summary>
    public void ShowInfo()
    {
        Console.WriteLine("我是一個圓形瓶蓋,我的直徑是2cm。");
    }
}
/// <summary>
/// 方形瓶子
/// </summary>
public class SquareCap : ICap
{
    /// <summary>
    /// 展示自己的信息
    /// </summary>
    public void ShowInfo()
    {
        Console.WriteLine("我是一個方形瓶蓋,我的直徑是5cm。");
    }
}

定義創建瓶子和瓶蓋的簡單工廠

/// <summary>
/// 瓶子創建工廠方法
/// </summary>
public class BottleFactory
{
    /// <summary>
    /// 創建瓶子對象
    /// </summary>
    /// <param name="color">瓶子顏色</param>
    /// <returns></returns>
    public static IBottle CreateBottle(string color)
    {
        if (color == "red")
            return new RedBottle();
        if (color == "blue")
            return new BlueBottle();
        return null;
    }
}
/// <summary>
/// 瓶蓋創建工廠方法
/// </summary>
public class CapFactory
{
    /// <summary>
    /// 創建瓶子對象
    /// </summary>
    /// <param name="shape">瓶蓋形狀</param>
    /// <returns></returns>
    public static ICap CreateCap(string shape)
    {
        if (shape == "round")
            return new RoundCap();
        if (shape == "square")
            return new SquareCap();
        return null;
    }
}

最終成品組裝類定義

/// <summary>
/// 隱形藥水組裝者
/// </summary>
public class ProductMaker
{
    private IBottle _bottle; // 瓶子對象
    private ICap _cap; // 瓶蓋對象

    /// <summary>
    /// 創建最終藥水對象
    /// </summary>
    /// <param name="bottleColor"></param>
    /// <param name="capShape"></param>
    public void MakeProduct(string bottleColor, string capShape)
    {
        _bottle = BottleFactory.CreateBottle(bottleColor);
        _cap = CapFactory.CreateCap(capShape);
        Console.WriteLine("準備英雄需要的瓶子和瓶蓋。");
        _bottle.ShowInfo();
        _cap.ShowInfo();
        Console.WriteLine("開始往瓶子了灌入隱形藥水,然後封上瓶蓋。");
    }
}

客戶端調用

static void Main(string[] args)
{
    ProductMaker pm = new ProductMaker();
    pm.MakeProduct("red", "round"); // 提供給英雄紅瓶子圓蓋子的隱形藥水
    Console.WriteLine();
    pm.MakeProduct("blue", "square"); // 提供給英雄藍瓶子方蓋子的隱形藥水
    Console.ReadLine();
}

這樣,我們通過介面進行隔離,解決了不同瓶子,不同蓋子創建時,客戶端無需關心具體創建過程,只需要告訴工廠需要何種類型的對象即可。但同時會暴露一個很明顯的問題就是,我們創建的瓶子和瓶蓋2個對象並不是孤立存在的,2個對象之間是有明顯的相互關係的,那就是平口尺寸必須和瓶蓋尺寸保持一直,否則就會讓店老闆出現灌裝好藥水卻擰不上蓋子的尷尬。此時應該會對上面提到的抽象工廠的定義有進一步的理解,也在這種場景下,是我們必須要引入抽象工廠模式的時候了。

1 抽象工廠模式詳解

0、提煉抽象工廠類

根據抽象工廠方法的結構圖,我們首先定義個一個抽象工廠類,該抽象工廠定義瓶子和瓶蓋2個對象的創建介面。

/// <summary>
/// 抽象工廠類
/// </summary>
public abstract class AbstractFactory
{
    /// <summary>
    /// 創建瓶子
    /// </summary>
    /// <returns></returns>
    public abstract IBottle CreateBottle();

    /// <summary>
    /// 創建瓶蓋
    /// </summary>
    /// <returns></returns>
    public abstract ICap CreateCap();
}

1、抽象工廠的具體實現

分析產品的組合情況,實際上只存在2種類型的最終產品,紅瓶子圓蓋子和藍瓶子方蓋子,我們分別定義2個抽象工廠的具體實現類

/// <summary>
/// 紅瓶子圓蓋子工廠類
/// </summary>
public class RedBottleAndRoundCapFactory : AbstractFactory
{
    /// <summary>
    /// 創建瓶子
    /// </summary>
    /// <returns></returns>
    public override IBottle CreateBottle()
    {
        return BottleFactory.CreateBottle("red");
    }

    /// <summary>
    /// 創建瓶蓋
    /// </summary>
    /// <returns></returns>
    public override ICap CreateCap()
    {
        return CapFactory.CreateCap("round");
    }
}
/// <summary>
/// 藍瓶子方蓋子工廠類
/// </summary>
public class BlueBottleAndSquareCapFactory : AbstractFactory
{
    /// <summary>
    /// 創建瓶子
    /// </summary>
    /// <returns></returns>
    public override IBottle CreateBottle()
    {
        return BottleFactory.CreateBottle("blue");
    }

    /// <summary>
    /// 創建瓶蓋
    /// </summary>
    /// <returns></returns>
    public override ICap CreateCap()
    {
        return CapFactory.CreateCap("square");
    }
}

2、最終產品組裝類的修改實現

跟原來的實現相比較,最終產品組裝類不在從客戶端傳入瓶子、瓶蓋的參數通過對應的工廠方法創建,而是直接傳入已經定義好的瓶子瓶蓋組裝工廠類對象,能夠做到瓶子瓶蓋必須配套創建。

/// <summary>
/// 創建最終藥水對象
/// </summary>
/// <param name="factory">抽象工廠具體對象</param>
public void MakeProduct(AbstractFactory factory)
{
    _bottle = factory.CreateBottle();
    _cap = factory.CreateCap();
    Console.WriteLine("準備英雄需要的瓶子和瓶蓋。");
    _bottle.ShowInfo();
    _cap.ShowInfo();
    Console.WriteLine("開始往瓶子了灌入隱形藥水,然後封上瓶蓋。");
}

3、客戶端調用

ProductMaker pm = new ProductMaker();
AbstractFactory factory = new RedBottleAndRoundCapFactory(); // 提供給英雄紅瓶子圓蓋子的隱形藥水
pm.MakeProduct(factory);
Console.WriteLine();
factory = new BlueBottleAndSquareCapFactory(); // 提供給英雄藍瓶子方蓋子的隱形藥水
pm.MakeProduct(factory);
Console.ReadLine();

2 總結

通過創建的多個對象之間的關聯關係闡述了抽象工廠模式與其他工廠模式的區別以及使用時機。基於上面的示例,我們可以總結出抽象工廠模式的具有以下優點:

0、分離介面和實現

客戶端使用抽象工廠方法來創建需要的對象,只需要傳入抽象方法的,無需關註內部具體實現邏輯,實現介面與具體實現的分離解耦。

1、易於產品族切換

一個具體抽象工廠的實現其實就是代表一個產品族,客戶端通過參數選用不同的工廠實現,就可以在不同的產品創建中進行切換。

抽象工廠模式的缺點也顯而易見,那就是擴展新產品的過程會比較麻煩,比如一個產品族中包含的產品發生了變化,比如增加或減少部件,就需要修改抽象工廠,同時需要修改所有的抽象工廠實現類。


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

-Advertisement-
Play Games
更多相關文章
  • 博客園地址:天清如願的博客。 ...
  • 轉載:http://blog.csdn.net/inter_peng/article/details/41021727 1. Action/Service/DAO簡介: Action是管理業務(Service)調度和管理跳轉的。 Service是管理具體的功能的。 Action只負責管理,而Serv ...
  • 浮點數是電腦中儲存實數的形式。我們時常需要用浮點數去處理帶小數點的運算。可你是否知道,浮點數還有這些操作: 正負無窮大 與整數不同,浮點數沒有溢出的概念。當浮點數的運算結果超過一定範圍時,它的值就會根據運算結果的符號變成正無窮大或負無窮大。最簡單產生無窮大的運算就是除以0.例如1.0/0.0的結果 ...
  • 在學習python的時候,三大“名器”對沒有其他語言編程經驗的人來說,應該算是一個小難點,本次博客就博主自己對裝飾器、迭代器和生成器理解進行解釋。 為什麼要使用裝飾器 什麼是裝飾器?“裝飾”從字面意思來誰就是對特定的建築物內按照一定的思路和風格進行美化的一種行為,所謂“器”就是工具,對於python ...
  • 實現介面自動化持續集成操作,具體操作步驟如下: windows - jenkins簡單安裝配置: 1. 下載最新版本的jenkins,jenkins官網地址:http://Jenkins-ci.org/ 2. 運行jenkins,找到jenkins.war所在目錄,執行命令:java -jar je ...
  • 在我們的日常項目開發過程中緩存是無處不在的,因為它可以極大的提高系統的訪問速度,關於緩存的框架也種類繁多,今天主要介紹的是使用現在非常流行的NoSQL資料庫(Redis)來實現我們的緩存需求。 ...
  • C#中double和float類型有兩個特殊值: Infinity(無窮大):5.0 / 0.0 = Infinity NaN(not a number):0.0 / 0.0 = NaN 計算表達式 0.0 / 0.0 = NaN, NaN和Infinity可以在表達式中使用: 10 + Infin ...
  • 閱讀目錄 前言 成熟的解決方案 剖析 實戰 服務治理的擴展 一、前言 首先本文僅作為筆者在做一些調研之後的總結,僅提供思路,不提供源碼,所以如果是想直接衝著源碼來的,可以跳過此文。如果後續有機會將項目開源出來,會第一時間寫新文章講解實線細節。 在分散式系統的構建之中,服務治理是類似血液一樣的存在,一 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...