C++|設計模式(三)|抽象工廠模式

抽象工廠模式仍然屬于創建型模式,我們在【簡單工廠和工廠方法模式】這篇文章中,描述了簡單工廠和工廠方法模式,并在文末,簡單介紹了工廠方法模式的局限性。

本文將通過汽車工廠的例子繼續來闡述使用抽象工廠模式相比較于工廠方法模式的優勢。

文章目錄

  • 工廠方法模式回顧
  • 抽象工廠模式
    • 代碼使用
    • 抽象工廠的局限性

工廠方法模式回顧

工廠方法模式通過允許類將實例化延遲到子類中來實現,使得增加新的產品類不需要修改現有系統的代碼。例如,一個汽車制造商需要不同類型的汽車,如寶馬、奧迪等,每種汽車的制造過程可能不同:

#include <iostream>
#include <string>
#include <memory>
using namespace std;class Car {
public:Car(string name) : name_(name) { }virtual ~Car(){}virtual void show() = 0;
protected:string name_;
};class Bmw : public Car {
public:Bmw(string name) : Car(name) { }void show() { cout << "獲得一輛寶馬汽車 " << name_ <<endl; }
};class Audi : public Car {
public:Audi(string name) : Car(name) { }void show() { cout << "獲得一輛奧迪汽車 " << name_ << endl; }
};//工廠方法
class Factory {
public:virtual ~Factory() {}virtual Car* createCar(string name) = 0; //工廠方法
};//寶馬工廠
class BMWFactory : public Factory {
public:Car* createCar(string name) { return new Bmw(name); }
};
//奧迪工廠
class AudiFactory : public Factory {
public:Car* createCar(string name) { return new Audi(name); }
};int main () {unique_ptr<Factory> bmwFactory(new BMWFactory());unique_ptr<Factory> audiFactory(new AudiFactory());unique_ptr<Car> p1(bmwFactory->createCar("X6"));unique_ptr<Car> p2(audiFactory->createCar("A8"));p1->show();p2->show();return 0;
}

現在,我們考慮這樣一種情況,如果我們現在要生產的產品是一組有關聯的產品簇怎么辦?難道我們像工廠方法一樣,又新建立一個工廠來生產該產品嗎?

比如說,我們之前有了奧迪工廠和寶馬工廠,現在我們需要生產奧迪車燈和寶馬車燈,難道又建立奧迪車燈工廠嗎?

這樣的話,最后我們需要管理的工廠(類)那也太多了,所以,很容易想到:

我們應該對一組有關聯關系的產品簇提供產品對象的統一創建。這就是抽象工廠模式。

抽象工廠模式

我們把之前的工廠方法類寫成抽象工廠類,并且里面提供創建車燈的方法,

并且,我們直接在寶馬工廠和奧迪工廠去創建車燈:

//系列產品一:汽車
class Car {
public:Car(string name) : name_(name) { }virtual ~Car(){}virtual void show() = 0;
protected:string name_;
};
class Bmw : public Car {
public:Bmw(string name) : Car(name) { }void show() { cout << "獲得一輛寶馬汽車 " << name_ <<endl; }
};
class Audi : public Car {
public:Audi(string name) : Car(name) { }void show() { cout << "獲得一輛奧迪汽車 " << name_ << endl; }
};
//系列產品二:車燈
class Light {
public:virtual ~Light() {}virtual void show() = 0;
};
class BmwLight : public Light{
public:void show() { cout << "BMW light!" << endl;};
};
class AudiLight : public Light{
public:void show() { cout << "Audi light!" << endl;};
};//工廠方法 =》 抽象工廠(對一組有關聯關系的產品簇提供產品對象的統一創建)
class AbstractFactory {
public:virtual ~AbstractFactory() {}virtual Car* createCar(string name) = 0; //工廠方法 創建汽車virtual Light* createLight() = 0; // 工廠方法 創建汽車關聯的產品--車燈
};//寶馬工廠
class BMWFactory : public AbstractFactory {
public:Car* createCar(string name) { return new Bmw(name); }Light* createLight() {return new BmwLight();}
};
//奧迪工廠
class AudiFactory : public AbstractFactory {
public:Car* createCar(string name) { return new Audi(name); }Light* createLight() {return new AudiLight();}
};

代碼使用

int main () {unique_ptr<AbstractFactory> bmwFactory(new BMWFactory());unique_ptr<AbstractFactory> audiFactory(new AudiFactory());unique_ptr<Car> p1(bmwFactory->createCar("X6"));unique_ptr<Car> p2(audiFactory->createCar("A8"));unique_ptr<Light> l1(bmwFactory->createCarLight());unique_ptr<Light> l2(audiFactory->createCarLight());p1->show();l1->show();p2->show();l2->show();return 0;
}

抽象工廠的局限性

我們設想這樣一種場景,比如說我們的寶馬工廠需要創建一個新的類對象(產品),但是奧迪工廠并不需要,但是如果寶馬工廠想要創建該類,
我們也比賽在抽象工廠類中去定義這樣一個虛函數,盡管奧迪工廠并不需要創建該類對象,他還是不得不去重寫該虛函數。這樣是不符合邏輯的。

總結:
簡單工廠Simple Factory:
優點:把對象的創建封裝在一個接口函數里面,通過傳入不同的標識,返回創建的對象,用戶不用自己負責new對象,不用了解對象創建的詳細過程
缺點:提供創建對象實例的接口函數不閉合,不能對修改關閉
工廠方法Factory Method:
優點:Fatcory基類,提供了一個純虛函數(創建產品),定義派生類(具體產品的工廠)負責創建對應的產品,可以做到不同的產品,在不同的工廠里面創建,能夠對現有工廠,以及產品的修改關閉
缺點:實際上,很多產品是有管理關系的,屬于一個產品簇,不應該放在不同的工廠里面去創建,這樣一是不符合實際的產品對象創建邏輯,二是工廠類太多了,不好維護
抽象工廠Abstract Factory
優點:把有關聯關系的,屬于一個產品簇的所有產品創建的接口函數,放在一個抽象工廠里面AbstractFactory類,派生類(具體產品的工廠)應該負責創建該產品簇里面所有的產品。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/15426.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/15426.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/15426.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Linux修煉之路之馮系結構,操作系統

目錄 一&#xff1a;馮諾依曼體系結構 1.五大組件 2.存儲器存在的意義 3.幾個問題 二&#xff1a;操作系統 接下來的日子會順順利利&#xff0c;萬事勝意&#xff0c;生活明朗-----------林辭憂 一&#xff1a;馮諾依曼體系結構 我們當代的計算機的基本構成都是由馮諾依曼…

Kubernetes 容器編排

應用程序部署演變 主要有三個演變&#xff1a; 傳統部署&#xff1a;互聯網早期&#xff0c;會直接將應用程序部署在物理機上 優點&#xff1a;簡單&#xff0c;不需要其它技術的參與 缺點&#xff1a;不能為應用程序定義資源使用邊界&#xff0c;很難合理地分配計算資源&…

【開源】多語言大型語言模型的革新:百億參數模型超越千億參數性能

大型人工智能模型&#xff0c;尤其是那些擁有千億參數的模型&#xff0c;因其出色的商業應用表現而受到市場的青睞。但是&#xff0c;直接通過API使用這些模型可能會帶來數據泄露的風險&#xff0c;尤其是當模型提供商如OpenAI等可能涉及數據隱私問題時。私有部署雖然是一個解決…

PY32F003+RTL8710(AT) 實現獲取天氣情況

一、RTL8710主要AT指令 1、ATSR&#xff1a;模塊重啟 2、ATSE1&#xff1a;開啟回顯 3、ATPW1&#xff1a;station模式 4、ATPNssid,password,,&#xff1a;連接到AP 5、ATPK1&#xff1a;設置自動接收 6、ATPC0,v1.yiketianqi.com,80&#xff1a;與網站建立TCP連接 7、ATPT125…

關于pytorch加載模型報錯問題

load_net[“params”] 報keyerror 加載模型后查看對應參數是什么 model2 torch.load(m1_path "xxx.pth") print(model1.keys())若輸出如下&#xff1a; 已經有相應參數不需要執行 load_net[“params”]若輸出如下 則需要load_net[“params”]

Linux-命令上

at是一次性的任務&#xff0c;crond是循環的定時任務 如果 cron.allow 文件存在&#xff0c;只有在文件中出現其登錄名稱的用戶可以使用 crontab 命令。root 用戶的登錄名必須出現在 cron.allow 文件中&#xff0c;如果這個文件存在的話。系統管理員可以明確的停止一個用戶&am…

3D 生成重建014-Bidiff使用二維和三維先驗的雙向擴散

3D 生成重建014-Bidiff使用二維和三維先驗的雙向擴散 文章目錄 0 論文工作1 論文方法2 效果 0 論文工作 大多數三維生成研究集中在將二維基礎模型向上投影到三維空間中&#xff0c;要么通過最小化二維評分蒸餾采樣&#xff08;SDS&#xff09;損失&#xff0c;要么通過對多視圖…

判斷變量是否為數組的幾種方法

1、isArray 方法 isArray() 方法用于判斷一個對象是否為數組。如果對象是數組返回 true&#xff0c;否則返回 false。 Array.isArray(arr); // true 1 2、對象原型 通過原型鏈判斷是否具有和數組同一原型鏈的頂端。 arr.__proto__ Array.prototype; // true 1 3、instanceof…

[數據結構] -- 雙向循環鏈表

&#x1f308; 個人主頁&#xff1a;白子寰 &#x1f525; 分類專欄&#xff1a;C打怪之路&#xff0c;python從入門到精通&#xff0c;數據結構&#xff0c;C語言&#xff0c;C語言題集&#x1f448; 希望得到您的訂閱和支持~ &#x1f4a1; 堅持創作博文(平均質量分82)&#…

一文理清database/sql包的使用場景和宕機查詢流程

一文理清database/sql包你可能遇到的問題 那么database/sql包實現了什么功能呢&#xff1f;建立數據庫連接檢測連接是否能ping通通過連接進行具體的sql查詢查詢完將連接進行關閉當數據庫宕掉重啟后再次查詢 database/sql包創建的db連接 對于數據庫宕掉后重啟是否仍然有效&#…

AI繪畫工具:創意與技術的完美融合

隨著人工智能技術的飛速發展&#xff0c;我們見證了無數領域的革新與變革。其中&#xff0c;AI繪畫工具的出現&#xff0c;無疑為藝術界帶來了一股清新的風潮。這些工具以其獨特的魅力&#xff0c;吸引了無數藝術家和創意人士的目光&#xff0c;成為他們表達自我、探索未知的重…

Compose在xml中使用滑動沖突處理

一、背景 在現有Android項目中使用Compose可能存在滑動沖突問題&#xff0c;例如 SmartRefreshLayoutCoordinatorLayoutComposeView(ComposeView這里又是一個LazyColumn) 二、解決方案 官方介紹&#xff1a;https://developer.android.google.cn/develop/ui/compose/touch-inp…

huggingface 筆記:device_map

1 基本映射方法 設計設備映射時&#xff0c;可以讓Accelerate庫來處理設備映射的計算通過設置device_map為支持的選項之一&#xff08;"auto"、 "balanced"、 "balanced_low_0"、 "sequential"&#xff09;&#xff1b;或者如果想更精…

golang的context和chan 的使用

1. context 作用 context包的context的接口&#xff0c;主要是控制協程執行上下文的時間&#xff0c;以及取消程序的執行&#xff0c;以及上下文中傳遞數據等作用&#xff0c;golang中耗時或者需要協同的操作都會見到context的身影。 context有幾個常用的方法 1.1 context.B…

用爬山算法解決離散的優化問題

爬山算法&#xff0c;也稱為梯度上升算法或局部搜索算法&#xff0c;是一種簡單有效的優化算法&#xff0c;常用于解決連續或離散的優化問題。爬山算法的基本思想是從一個隨機的初始點開始&#xff0c;通過迭代地向局部最優的方向移動&#xff0c;逐步逼近全局最優解。 爬山算…

git管理Codeup云效平臺

HTTPS方式實現Git命令 1.進入項目路徑&#xff0c;如 cd demo&#xff0c;與此同時&#xff0c;在Codeup平臺創建一個空倉庫repo&#xff0c;獲取空倉庫的https協議地址&#xff0c;例如 https://codeup.aliyun.com/xxxx/xxxx/xxx.git。 2.在demo項目下執行 git init命令初始化…

從反向傳播(BP)到BPTT:詳細數學推導【原理理解】

從反向傳播到BPTT&#xff1a;詳細推導與問題解析 在本文中&#xff0c;我們將從反向傳播算法開始&#xff0c;詳細推導出反向傳播通過時間&#xff08;Backpropagation Through Time, BPTT&#xff09;算法。重點討論BPTT中的梯度消失和梯度爆炸問題&#xff0c;并解釋如何解…

采用LoRA方法微調llama3大語言模型

文章目錄 前言一、Llama3模型簡介1.下載llama3源碼到linux服務器2.安裝依賴3.測試預訓練模型Meta-Llama-3-8B4.測試指令微調模型Meta-Llama3-8B-Instruct5.小結 二、LoRA微調Llama31.引入庫2.編寫配置文件3.LoRA訓練的產物 三、測試新模型效果1.編寫配置文件2.運行配置文件&…

QT教程-一,初識QT

目錄 一,QT是什么&#xff1f;能夠使用它做什么&#xff1f; 二&#xff0c;Qt 能夠使用的語言 三&#xff0c;Qt主要用于什么領域&#xff1f; 四&#xff0c;Qt開發的軟件 一,QT是什么&#xff1f;能夠使用它做什么&#xff1f; Qt是一個跨平臺的 C 開發庫&#xff0c;主…

全球最高點贊記錄,世界點贊第一名是誰?世界點贊第一人名字的由來

世界點贊第一人名字的由來&#xff1a; 起源與概念提出&#xff1a; 二十一世紀東方偉大的思想家哲學家教育家顏廷利教授&#xff0c;一位在中國21世紀早期便以其非凡才華和創新精神著稱的學者&#xff0c;早在互聯網尚未普及的20世紀90年代&#xff0c;就已經提出了“點贊”的…