C++ 深入淺出工廠模式(初識篇)

来源:https://www.cnblogs.com/xiaolincoding/archive/2019/09/15/11524376.html
-Advertisement-
Play Games

初識工廠模式 我們先看工廠模式的介紹 這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。 在工廠模式中,我們在創建對象時不會對客戶端暴露創建邏輯,並且是通過使用一個共同的介面來指向新創建的對象。 簡單來說,使用了C++ 多態 的特性,將存在 繼承 關係的類,通過一個 工廠類創建 對應 ...


初識工廠模式

我們先看工廠模式的介紹

這種類型的設計模式屬於創建型模式,它提供了一種創建對象的最佳方式。
在工廠模式中,我們在創建對象時不會對客戶端暴露創建邏輯,並且是通過使用一個共同的介面來指向新創建的對象。

簡單來說,使用了C++多態的特性,將存在繼承關係的類,通過一個工廠類創建對應的子類(派生類)對象。在項目複雜的情況下,可以便於子類對象的創建。

工廠模式的實現方式可分別簡單工廠模式工廠方法模式抽象工廠模式,每個實現方式都存在優和劣。

最近炒鞋炒的非常的火,那麼以鞋廠的形式,一一分析針對每個實現方式進行分析。


簡單工廠模式

具體的情形:
  • 鞋廠可以指定生產耐克、阿迪達斯和李寧牌子的鞋子。哪個鞋炒的火爆,老闆就生產哪個,看形勢生產。
UML圖:

簡單工廠模式的結構組成
  1. 工廠類(ShoesFactory):工廠模式的核心類,會定義一個用於創建指定的具體實例對象的介面。
  2. 抽象產品類(Shoes):是具體產品類的繼承的父類或實現的介面。
  3. 具體產品類(NiKeShoes\AdidasShoes\LiNingShoes):工廠類所創建的對象就是此具體產品實例。
簡單工廠模式的特點
  • 工廠類封裝了創建具體產品對象的函數。
簡單工廠模式的缺陷
  • 擴展性非常差,新增產品的時候,需要去修改工廠類。
簡單工廠模式的代碼
  • Shoes為鞋子的抽象類(基類),介面函數為Show(),用於顯示鞋子廣告。
  • NiKeShoesAdidasShoesLiNingShoes為具體鞋子的類,分別是耐克、阿迪達斯和李寧鞋牌的鞋,它們都繼承於Shoes抽象類。
// 鞋子抽象類
class Shoes
{
public:
    virtual ~Shoes() {}
    virtual void Show() = 0;
};

// 耐克鞋子
class NiKeShoes : public Shoes
{
public:
    void Show()
    {
        std::cout << "我是耐克球鞋,我的廣告語:Just do it" << std::endl;
    }
};

// 阿迪達斯鞋子
class AdidasShoes : public Shoes
{
public:
    void Show()
    {
        std::cout << "我是阿迪達斯球鞋,我的廣告語:Impossible is nothing" << std::endl;
    }
};

// 李寧鞋子
class LiNingShoes : public Shoes
{
public:
    void Show()
    {
        std::cout << "我是李寧球鞋,我的廣告語:Everything is possible" << std::endl;
    }
};
  • ShoesFactory為工廠類,類里實現根據鞋子類型創建對應鞋子產品對象的CreateShoes(SHOES_TYPE type)函數。
enum SHOES_TYPE
{
    NIKE,
    LINING,
    ADIDAS
};

// 總鞋廠
class ShoesFactory
{
public:
    // 根據鞋子類型創建對應的鞋子對象
    Shoes *CreateShoes(SHOES_TYPE type)
    {
        switch (type)
        {
        case NIKE:
            return new NiKeShoes();
            break;
        case LINING:
            return new LiNingShoes();
            break;
        case ADIDAS:
            return new AdidasShoes();
            break;
        default:
            return NULL;
            break;
        }
    }
};
  • main函數,先是構造了工廠對象,後創建指定類型的具體鞋子產品對象,創建了具體鞋子產品的對象便可直接列印廣告。因為採用的是new的方式創建了對象,用完了要通過delete 釋放資源資源哦!
int main()
{
    // 構造工廠對象
    ShoesFactory shoesFactory;

    // 從鞋工廠對象創建阿迪達斯鞋對象
    Shoes *pNikeShoes = shoesFactory.CreateShoes(NIKE);
    if (pNikeShoes != NULL)
    {
        // 耐克球鞋廣告喊起
        pNikeShoes->Show();

        // 釋放資源
        delete pNikeShoes;
        pNikeShoes = NULL;
    }

    // 從鞋工廠對象創建阿迪達斯鞋對象
    Shoes *pLiNingShoes = shoesFactory.CreateShoes(LINING);
    if (pLiNingShoes != NULL)
    {
        // 李寧球鞋廣告喊起
        pLiNingShoes->Show();

        // 釋放資源
        delete pLiNingShoes;
        pLiNingShoes = NULL;
    }

    // 從鞋工廠對象創建阿迪達斯鞋對象
    Shoes *pAdidasShoes = shoesFactory.CreateShoes(ADIDAS);
    if (pAdidasShoes != NULL)
    {
        // 阿迪達斯球鞋廣告喊起
        pAdidasShoes->Show();

        // 釋放資源
        delete pAdidasShoes;
        pAdidasShoes = NULL;
    }

    return 0;
}
  • 輸出結果:
[root@lincoding factory]# ./simpleFactory 
我是耐克球鞋,我的廣告語:Just do it
我是阿迪達斯球鞋,我的廣告語:Impossible is nothing
我是李寧球鞋,我的廣告語:Everything is possible

工廠方法模式

具體情形:
  • 現各類鞋子抄的非常火熱,於是為了大量生產每種類型的鞋子,則要針對不同品牌的鞋子開設獨立的生產線,那麼每個生產線就只能生產同類型品牌的鞋。
UML圖:

工廠方法模式的結構組成
  1. 抽象工廠類廠(ShoesFactory):工廠方法模式的核心類,提供創建具體產品的介面,由具體工廠類實現。
  2. 具體工廠類NiKeProducer\AdidasProducer\LiNingProducer):繼承於抽象工廠,實現創建對應具體產品對象的方式。
  3. 抽象產品類Shoes):它是具體產品繼承的父類(基類)。
  4. 具體產品類NiKeShoes\AdidasShoes\LiNingShoes):具體工廠所創建的對象,就是此類。
工廠方法模式的特點
  • 工廠方法模式抽象出了工廠類,提供創建具體產品的介面,交由子類去實現。
  • 工廠方法模式的應用並不只是為了封裝具體產品對象的創建,而是要把具體產品對象的創建放到具體工廠類實現。
工廠方法模式的缺陷
  • 每新增一個產品,就需要增加一個對應的產品的具體工廠類。相比簡單工廠模式而言,工廠方法模式需要更多的類定義。
  • 一條生產線只能一個產品。
工廠方法模式的代碼:
  • ShoesFactory抽象工廠類,提供了創建具體鞋子產品的純虛函數。
  • NiKeProducerAdidasProducerLiNingProducer具體工廠類,繼承持續工廠類,實現對應具體鞋子產品對象的創建。
// 總鞋廠
class ShoesFactory
{
public:
    virtual Shoes *CreateShoes() = 0;
    virtual ~ShoesFactory() {}
};

// 耐克生產者/生產鏈
class NiKeProducer : public ShoesFactory
{
public:
    Shoes *CreateShoes()
    {
        return new NiKeShoes();
    }
};

// 阿迪達斯生產者/生產鏈
class AdidasProducer : public ShoesFactory
{
public:
    Shoes *CreateShoes()
    {
        return new AdidasShoes();
    }
};

// 李寧生產者/生產鏈
class LiNingProducer : public ShoesFactory
{
public:
    Shoes *CreateShoes()
    {
        return new LiNingShoes();
    }
};
  • main函數針對每種類型的鞋子,構造了每種類型的生產線,再由每個生產線生產出對應的鞋子。需註意的是具體工廠對象和具體產品對象,用完了需要通過delete釋放資源。
int main()
{
    // ================ 生產耐克流程 ==================== //
    // 鞋廠開設耐克生產線
    ShoesFactory *niKeProducer = new NiKeProducer();
    // 耐克生產線產出球鞋
    Shoes *nikeShoes = niKeProducer->CreateShoes();
    // 耐克球鞋廣告喊起
    nikeShoes->Show();
    // 釋放資源
    delete nikeShoes;
    delete niKeProducer;

    // ================ 生產阿迪達斯流程 ==================== //
    // 鞋廠開設阿迪達斯生產者
    ShoesFactory *adidasProducer = new AdidasProducer();
    // 阿迪達斯生產線產出球鞋
    Shoes *adidasShoes = adidasProducer->CreateShoes();
    // 阿迪達斯球鞋廣喊起
    adidasShoes->Show();
    // 釋放資源
    delete adidasShoes;
    delete adidasProducer;

    return 0;
}
  • 輸出結果:
[root@lincoding factory]# ./methodFactory 
我是耐克球鞋,我的廣告語:Just do it
我是阿迪達斯球鞋,我的廣告語:Impossible is nothing

抽象工廠模式

具體情形:
  • 鞋廠為了擴大了業務,不僅只生產鞋子,把運動品牌的衣服也一起生產了。
UML圖:

抽象工廠模式的結構組成(和工廠方法模式一樣):
  1. 抽象工廠類廠(ShoesFactory):工廠方法模式的核心類,提供創建具體產品的介面,由具體工廠類實現。
  2. 具體工廠類NiKeProducer):繼承於抽象工廠,實現創建對應具體產品對象的方式。
  3. 抽象產品類Shoes\Clothe):它是具體產品繼承的父類(基類)。
  4. 具體產品類NiKeShoes\NiKeClothe):具體工廠所創建的對象,就是此類。
抽象工廠模式的特點:
  • 提供一個介面,可以創建多個產品族中的產品對象。如創建耐克工廠,則可以創建耐克鞋子產品、衣服產品、褲子產品等。
抽象工廠模式的缺陷:
  • 同工廠方法模式一樣,新增產品時,都需要增加一個對應的產品的具體工廠類。
抽象工廠摸是的代碼:
  • ClotheShoes,分別為衣服和鞋子的抽象產品類。
  • NiKeClotheNiKeShoes,分別是耐克衣服和耐克衣服的具體產品類。
// 基類 衣服
class Clothe
{
public:
    virtual void Show() = 0;
    virtual ~Clothe() {}
};

// 耐克衣服
class NiKeClothe : public Clothe
{
public:
    void Show()
    {
        std::cout << "我是耐克衣服,時尚我最在行!" << std::endl;
    }
};

// 基類 鞋子
class Shoes
{
public:
    virtual void Show() = 0;
    virtual ~Shoes() {}
};

// 耐克鞋子
class NiKeShoes : public Shoes
{
public:
    void Show()
    {
        std::cout << "我是耐克球鞋,讓你酷起來!" << std::endl;
    }
};
  • Factory為抽象工廠,提供了創建鞋子CreateShoes()和衣服產品CreateClothe()對象的介面。
  • NiKeProducer為具體工廠,實現了創建耐克鞋子和耐克衣服的方式。
// 總廠
class Factory
{
public:
    virtual Shoes *CreateShoes() = 0;
    virtual Clothe *CreateClothe() = 0;
    virtual ~Factory() {}
};

// 耐克生產者/生產鏈
class NiKeProducer : public Factory
{
public:
    Shoes *CreateShoes()
    {
        return new NiKeShoes();
    }
    
    Clothe *CreateClothe()
    {
        return new NiKeClothe();
    }
};
  • main函數,構造耐克工廠對象,通過耐克工廠對象再創建耐克產品族的衣服和鞋子對象。同樣,對象不再使用時,需要手動釋放資源。
int main()
{
    // ================ 生產耐克流程 ==================== //
    // 鞋廠開設耐克生產線
    Factory *niKeProducer = new NiKeProducer();
    
    // 耐克生產線產出球鞋
    Shoes *nikeShoes = niKeProducer->CreateShoes();
    // 耐克生產線產出衣服
    Clothe *nikeClothe = niKeProducer->CreateClothe();
    
    // 耐克球鞋廣告喊起
    nikeShoes->Show();
    // 耐克衣服廣告喊起
    nikeClothe->Show();
    
    // 釋放資源
    delete nikeShoes;
    delete nikeClothe;
    delete niKeProducer;


    return 0;
}
  • 輸出結果:
[root@lincoding factory]# ./abstractFactory 
我是耐克球鞋,讓你酷起來!
我是耐克衣服,時尚我最在行!

總結

以上三種工廠模式,在新增產品時,都存在一定的缺陷。

  • 簡單工廠模式,,需要去修改工廠類,這違背了開閉法則。
  • 工廠方式模式和抽象工廠模式,都需要增加一個對應的產品的具體工廠類,這就會增大了代碼的編寫量。

那麼有什麼好的方法,在新增產品時,即不用修改工廠類,也不用新增具體的工廠類?

筆者在實際項目中看到一個封裝性非常強的工廠類,在擴展新產品時,不需要修改工廠類,也不需要新增具體的工廠類,詳細內容可以跳轉至C++ 深入淺出工廠模式(進階篇)閱讀。


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

-Advertisement-
Play Games
更多相關文章
  • 本代碼演示: 1. pandas讀取純文本文件 讀取csv文件 讀取txt文件 2. pandas讀取xlsx格式excel文件 3. pandas讀取mysql數據表 1、讀取純文本文件 1.1 讀取CSV,使用預設的標題行、逗號分隔符 .dataframe tbody tr th:only of ...
  • Servlet的生命周期分為5個階段:載入、創建、初始化、處理客戶請求、卸載。 (1)載入:容器通過類載入器使用servlet類對應的文件載入servlet (2)創建:通過調用servlet構造函數創建一個servlet對象 (3)初始化:調用init方法初始化 (4)處理客戶請求:每當有一個客戶 ...
  • Django之使用內置函數和celery發郵件,內容包括 發送郵件前的郵箱配置,使用Django內置函數發郵件,使用celery發郵件。在開發項目時,特別是用戶註冊時,我們通常都要給用戶發送郵件驗證註冊,那麼在Django中如何發郵件呢?這裡例舉了兩種方式來給用戶發送郵件,並且創建一個項目之後複製代... ...
  • 本文源碼: "GitHub·點這裡" || "GitEE·點這裡" 一、觀察者模式 1、概念描述 觀察者模式是對象的行為模式,又叫發佈 訂閱(Publish/Subscribe)模式。觀察者模式定義了一種一對多的依賴關係,讓多個觀察者對象同時監聽某一個主題對象,主題對象在狀態發生變化時,會通知所有觀 ...
  • jdbc 動力節點視頻教程 JDBC編程六步 1.註冊驅動(作用:告訴Java程式,即將要連接的是哪個品牌的資料庫) 2.獲取連接 (表示JVM進程和資料庫進程之間的通道打開了,屬於進程間的通信,重量級的,使用完一定要關閉) 3.獲取資料庫操作對象(專門執行SQL 語句的對象) 4.執行sql(主要 ...
  • 新聞 "宣告ML.NET 1.4的預覽版及更新模型構建器" ".NET展示會:一系列的活動!" "Octopus入門版:對於小團隊免費" "宣告.NET Core 3.0預覽版9" "使用IntelliCode更簡單地進行重構" ".NET Core 3.0預覽版9中ASP.NET Core與Bla ...
  • Python3實戰Spark大數據分析及調度 搜索QQ號直接加群獲取其它學習資料:715301384 部分課程截圖: 鏈接:https://pan.baidu.com/s/12VDmdhN4hr7ypdKTJvvgKg 提取碼:cv9z PS:免費分享,若點擊鏈接無法獲取到資料,若如若鏈接失效請加群 ...
  • 記憶體四區 代碼區:存放函數體第二進位代碼,由操作戲臺進行管理 數據區:存放全局變數和靜態變數以及常量 棧區:由編譯器自動分配釋放,存放函數的參數值,局部變數等 堆區:由程式員分配和釋放,若程式員不是放,程式結束時由操作系統回收 代碼區:存放函數體第二進位代碼,由操作戲臺進行管理 數據區:存放全局變數 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...