創建型模式:抽象工廠

来源:https://www.cnblogs.com/liebrother/archive/2019/01/20/10296253.html
-Advertisement-
Play Games

個人博客原文: "創建型模式:抽象工廠" 五大創建型模式之三:抽象工廠。 簡介 姓名 :抽象工廠 英文名 :Abstract Factory Pattern 價值觀 :不管你有多少產品,給我就是了 個人介紹 : Provide an interface for creating families o ...


個人博客原文:
創建型模式:抽象工廠

景

五大創建型模式之三:抽象工廠。

簡介

姓名 :抽象工廠

英文名 :Abstract Factory Pattern

價值觀 :不管你有多少產品,給我就是了

個人介紹

Provide an interface for creating families of related or dependent objects without specifying their concrete classes.
為創建一組相關或相互依賴的對象提供一個介面,而且無須指定它們的具體類。
(來自《設計模式之禪》)

今天講的是抽象工廠模式,小伙伴可能有疑問,抽象工廠和工廠方法之間都有工廠,那肯定是有什麼聯繫的,具體是什麼關係呢?簡單的說:工廠方法是在解決一個產品多個層級方面的事情;而抽象工廠致力於解決多個產品多個層級方面的事情。舉個例子:汽車是由很多零件組成的,比如引擎、輪胎、方向盤等等。現在如果我們是輪胎生產方,要生產寶馬輪胎和賓士輪胎,要用工廠方法還是抽象工廠實現呢?答案是:工廠方法。輪胎是一個產品,寶馬輪胎和賓士輪胎是 2 個不同層級的輪胎,所以用工廠方法解決就足夠。假如現在我們是汽車生產方,要生產寶馬汽車和賓士汽車,汽車又包含輪胎和方向盤等等,要用哪個來實現?既然是上面的是工廠方法,那這個就用抽象工廠,因為這涉及到多個產品(輪胎、方向盤等等)和 2 個層級(寶馬和賓士)。這裡還沒有講抽象工廠的概念就說了工廠方法和抽象方法的區別,是不是有點陌生?嗯,先記住這個概念,分清楚兩者的區別。在不同場景使用不同的設計模式。

上面定義中:為創建一組相關或相互依賴的對象提供一個介面。這樣子理解這句話,比如上面說的輪胎和方向盤,寶馬汽車用的輪胎和方向盤需要都是寶馬品牌的,也就是說在安裝寶馬汽車的輪胎和方向盤的時候,得用寶馬生產的輪胎和方向盤,重要的一點是:輪胎和方向盤是互相依賴的,不能在寶馬汽車上安裝賓士輪胎和寶馬方向盤,因為有這個依賴關係,所以我們需要提供一個額外的介面,來保證寶馬汽車使用的輪胎和方向盤都是寶馬生產的。這就是抽象工廠乾的事情。

你要的故事

上面用汽車安裝輪胎和方向盤的例子,那這裡為了讓大家能深入理解,就不用其他例子了。在一個設計模式講解的過程中,我覺得用一個案例來講解可以減少讀者的閱讀理解成本,為了寫設計模式這一系列文章,看了不少設計模式方面的書籍,有些書籍在講解一個設計模式的時候,用了不止一個例子,讀完之後印象不是很深刻。這個系列寫完之後,想要的效果是:不需要記住設計模式的定義,把這些故事以及故事對應是講哪個設計模式都記住了,就真正掌握了這些內容了。

public class AbstractFactoryTest {

    public static void main(String[] args) {
        // 寶馬員工安裝輪胎和方向盤
        AbstractCarFactory bmwCarFacatory = new BMWCarFactory();
        bmwCarFacatory.installWheel();
        bmwCarFacatory.installSteeringWheel();

        // 賓士員工安裝輪胎和方向盤
        AbstractCarFactory mercedesCarFacatory = new MercedesCarFacatory();
        mercedesCarFacatory.installWheel();
        mercedesCarFacatory.installSteeringWheel();
    }

}

/**
 * 汽車抽象工廠
 */
interface AbstractCarFactory {

    void installWheel();

    void installSteeringWheel();

}

/**
 * 寶馬工廠
 */
class BMWCarFactory implements AbstractCarFactory {

    @Override
    public void installWheel() {
        WheelFacatory wheelFacatory = new BMWWheelFacatory();
        String wheel = wheelFacatory.createWheel();
        System.out.println("安裝輪胎:" + wheel);
    }

    @Override
    public void installSteeringWheel() {
        SteeringWheelFacatory steeringWheelFacatory = new BMWSteeringWheelFacatory();
        String steeringWheel = steeringWheelFacatory.createSteeringWheel();
        System.out.println("安裝方向盤:" + steeringWheel);
    }
}

/**
 * 賓士工廠
 */
class MercedesCarFacatory implements AbstractCarFactory {

    @Override
    public void installWheel() {
        WheelFacatory wheelFacatory = new MercedesWheelFacatory();
        String wheel = wheelFacatory.createWheel();
        System.out.println("安裝輪胎:" + wheel);
    }

    @Override
    public void installSteeringWheel() {
        SteeringWheelFacatory steeringWheelFacatory = new MercedesSteeringWheelFacatory();
        String steeringWheel = steeringWheelFacatory.createSteeringWheel();
        System.out.println("安裝方向盤:" + steeringWheel);
    }
}

/**
 * 輪胎工廠
 */
interface WheelFacatory {

    String createWheel();

}

/**
 * 寶馬輪胎工廠
 */
class BMWWheelFacatory implements WheelFacatory {

    @Override
    public String createWheel() {
        System.out.println("寶馬輪胎工廠生產輪胎");
        return "寶馬輪胎";
    }
}

/**
 * 賓士輪胎工廠
 */
class MercedesWheelFacatory implements WheelFacatory {

    @Override
    public String createWheel() {
        System.out.println("賓士輪胎工廠生產輪胎");
        return "賓士輪胎";
    }
}

/**
 * 方向盤工廠
 */
interface SteeringWheelFacatory {

    String createSteeringWheel();

}

/**
 * 寶馬方向盤工廠
 */
class BMWSteeringWheelFacatory implements SteeringWheelFacatory {

    @Override
    public String createSteeringWheel() {
        System.out.println("寶馬方向盤工廠生產方向盤");
        return "寶馬方向盤";
    }
}

/**
 * 賓士方向盤工廠
 */
class MercedesSteeringWheelFacatory implements SteeringWheelFacatory {

    @Override
    public String createSteeringWheel() {
        System.out.println("賓士方向盤工廠生產方向盤");
        return "賓士方向盤";
    }
}

代碼:

AbstractFactoryTest.java

還是和以往一樣,思維開拓一下,這裡列舉的是給汽車安裝輪胎和方向盤,汽車不止這些,如果要加個安裝引擎呢?要怎麼實現?這裡我就不寫出來了,讓小伙伴嘗試一下,寫出來了就理解抽象模式這個設計模式啦。

總結

簡單工廠、工廠方法、抽象工廠這幾個工廠相關的設計模式的基本內容都講完了,這幾個模式都是為瞭解耦,為了可擴展。這裡要著重說一下,三者之間沒有好壞之分,只有在具體的場景才能發揮它們各自的優勢。在單產品多層級,層級數量不多的情況下,可以使用簡單工廠,層級多且需要支持擴展,可以使用工廠方法;在多產品多層級,可以使用抽象工廠。

參考資料:《大話設計模式》、《Java設計模式》、《設計模式之禪》、《研磨設計模式》、《Head First 設計模式》

推薦閱讀:
創建型模式:單例模式
創建型模式:工廠方法

希望文章對您有所幫助,設計模式系列會持續更新,感興趣的同學可以關註公眾號,第一時間獲取文章推送閱讀,也可以一起交流,交個朋友。

公眾號之設計模式系列文章

公眾號


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

-Advertisement-
Play Games
更多相關文章
  • 製作一套自己的 3D 的管道控制系統!運用了 HT 的 Graph3dView 組件通過對 WebGL 底層技術的封裝,與 HT 其他組件一樣,基於 HT 統一的 DataModel 數據模型來驅動圖形顯示。本篇主要包含動畫和思路等技術點。HT For Web 提供完整的基於 HTML5 圖形界面組... ...
  • 做過小試驗,主要用於美化界面、增強頁面內容交互性,無關安全性討論,一切全靠自覺. ...
  • 2019年計劃讀書30本以上,在此記錄下已經讀完的書。 1月 《看懂肢体語言:溝通中最重要的93%》 【已讀完 2019 01 02】 《軟技能:代碼之外的生存指南》 【已讀完 2019 01 06】 《一隻特立獨行的豬》 【已讀完 2019 01 12】 《創業基因》 【已讀完 2019 01 1 ...
  • 大家在做後臺管理系統時一般都會涉及到菜單的許可權控制問題。當然解決問題的方法無非兩種——前端控制和後端控制。我們公司這邊的產品迭代速度較快,所以我們是從前端控制路由迭代到後端控制路由。下麵我會分別介紹這兩種方法的優缺點以及如何實現(不熟悉vue-router API的同學可以先去官網看一波API哈)。 ...
  • 線上體驗地址:http://vip.52tech.tech/ GIthub源碼:https://github.com/xiugangzhang/vip.github.io 項目預覽 主頁面 登錄頁面 註冊頁面 會員中心 電影播放頁面 電影彈幕功能 視頻網站項目已經完功能如下: v1.0.3(當前最新 ...
  • 一 npm 方式 1,安裝依賴 (已有項目) 如果想簡單體驗:基於vue-cli /* npm install vue -g npm install vue-cli -g // -g 是否全局安裝,如果不需要可不加 vue init webpack mint-pro (一路回車預設即可) */ np ...
  • vue判斷是pc端還是移動端分別進入不同的頁面 判斷移動端代碼如下: 路由判斷分別進入pc還是移動端 判斷路由代碼如下: 通過user-agent值,來進行判斷,使用javascript框架中的Navigator對象的userAgent屬性 還有些其他方法可以根據個人項目是改動,僅個人學習筆記,希望 ...
  • datagrid 實現表格記錄拖拽 by:授客 QQ:1033553122 測試環境 jquery-easyui-1.5.3 jquery-easyui-datagrid-dnd 下載地址: http://www.jeasyui.net/demo/193.html 實現 編輯datagrid-dnd ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...