【C/C++】設計模式之工廠模式:從簡單到抽象的演進

文章目錄

  • 設計模式之工廠模式:從簡單到抽象的演進
    • 1 “工廠”模式分類
      • 1.1 簡單工廠(Simple Factory)
      • 1.2 工廠方法(Factory Method)
      • 1.3 抽象工廠(Abstract Factory)
    • 2 分析
    • 3 總結對比

設計模式之工廠模式:從簡單到抽象的演進

1 “工廠”模式分類

“工廠”模式在設計模式中是一個重要的創建型模式,它可以分為以下幾類:

1.1 簡單工廠(Simple Factory)

【不是 GOF 23 種經典設計模式之一】

  • 特點:由一個工廠類根據傳入參數決定創建哪種產品類。
  • 缺點:違反開閉原則,每新增一個產品就要修改工廠邏輯。
  • 適用場景:產品種類不多,變化不頻繁。
#include <iostream>
#include <memory>
#include <string>class Shape {
public:virtual void draw() = 0;virtual ~Shape() = default;
};class Circle : public Shape {
public:void draw() override {std::cout << "Drawing Circle\n";}
};class Rectangle : public Shape {
public:void draw() override {std::cout << "Drawing Rectangle\n";}
};class ShapeFactory {
public:static std::unique_ptr<Shape> createShape(const std::string& type) {if (type == "circle") return std::make_unique<Circle>();if (type == "rectangle") return std::make_unique<Rectangle>();return nullptr;}
};// 使用
int main() {auto shape = ShapeFactory::createShape("circle");if (shape) shape->draw();return 0;
}

1.2 工廠方法(Factory Method)

【GOF 經典設計模式之一】

  • 特點:定義一個用于創建對象的接口,讓子類決定實例化哪一個類。

  • 優點:符合開閉原則。

  • 適用場景:產品種類較多,或需要定制化創建流程。

  • 與簡單工廠區別:每個產品對應一個具體工廠類;新增產品只需新增一個工廠類,符合開閉原則。

#include <iostream>
#include <memory>class Shape {
public:virtual void draw() = 0;virtual ~Shape() = default;
};class Circle : public Shape {
public:void draw() override {std::cout << "Drawing Circle\n";}
};// 工廠基類
class ShapeFactory {
public:virtual std::unique_ptr<Shape> createShape() = 0;virtual ~ShapeFactory() = default;
};// 工廠子類
class CircleFactory : public ShapeFactory {
public:std::unique_ptr<Shape> createShape() override {return std::make_unique<Circle>();}
};// 使用
int main() {std::unique_ptr<ShapeFactory> factory = std::make_unique<CircleFactory>();auto shape = factory->createShape();shape->draw();return 0;
}

1.3 抽象工廠(Abstract Factory)

【GOF 經典設計模式之一】

  • 特點:提供一個接口,用于創建多個相關或依賴的對象族。

  • 優點:適合產品之間存在關系(如 UI 控件風格:Windows vs Mac)。

  • 適用場景:需要創建多個相互關聯的產品族,而不需要指定具體類。

  • 與前面工廠模式的區別:創建一組相關產品(產品族);適用于系統需要生產多個產品系列(如不同平臺的 UI)。

#include <iostream>
#include <memory>// 抽象產品
class Button {
public:virtual void paint() = 0;virtual ~Button() = default;
};class Checkbox {
public:virtual void toggle() = 0;virtual ~Checkbox() = default;
};// Windows 產品
class WindowsButton : public Button {
public:void paint() override {std::cout << "Windows Button\n";}
};class WindowsCheckbox : public Checkbox {
public:void toggle() override {std::cout << "Windows Checkbox toggled\n";}
};// Mac 產品
class MacButton : public Button {
public:void paint() override {std::cout << "Mac Button\n";}
};class MacCheckbox : public Checkbox {
public:void toggle() override {std::cout << "Mac Checkbox toggled\n";}
};// 抽象工廠
class GUIFactory {
public:virtual std::unique_ptr<Button> createButton() = 0;virtual std::unique_ptr<Checkbox> createCheckbox() = 0;virtual ~GUIFactory() = default;
};// Windows 工廠
class WindowsFactory : public GUIFactory {
public:std::unique_ptr<Button> createButton() override {return std::make_unique<WindowsButton>();}std::unique_ptr<Checkbox> createCheckbox() override {return std::make_unique<WindowsCheckbox>();}
};// Mac 工廠
class MacFactory : public GUIFactory {
public:std::unique_ptr<Button> createButton() override {return std::make_unique<MacButton>();}std::unique_ptr<Checkbox> createCheckbox() override {return std::make_unique<MacCheckbox>();}
};// 使用
int main() {std::unique_ptr<GUIFactory> factory = std::make_unique<WindowsFactory>();auto button = factory->createButton();auto checkbox = factory->createCheckbox();button->paint();checkbox->toggle();return 0;
}

2 分析

簡單工廠模式通過一個固定工廠類根據參數決定創建哪個單一產品對象,它是一種集中式、非繼承的設計;

工廠方法模式將創建邏輯交由各自的工廠子類實現,滿足開閉原則,適用于單一產品類的靈活擴展;

抽象工廠模式在工廠方法的基礎上增加了“產品族(多個相關產品)”的抽象接口,統一生產一組彼此關聯的產品,實現更高級別的解耦和擴展。

設計模式核心思想是否使用繼承
簡單工廠使用一個類集中管理對象創建(if-else
工廠方法為每個產品定義一個創建類(工廠子類)
抽象工廠為一組產品族提供統一創建接口

輔助記憶方法:
簡單工廠 = 統一超市收銀臺:你買啥,告訴我商品代碼,我幫你找。
工廠方法 = 各品牌有獨立專賣店:你要耐克去耐克店,要阿迪去阿迪店。
抽象工廠 = 同一品牌店提供一整套商品組合(鞋、衣服、帽子):Nike-全套,Adidas-全套。


3 總結對比

模式是否符合開閉原則是否屬于 GOF 設計模式創建方式應用場景
簡單工廠不符合一個工廠方法創建所有產品產品種類較少,創建邏輯簡單,變化不頻繁
工廠方法符合一個產品一個工廠產品種類較多,需擴展性
抽象工廠符合一組產品族使用一個工廠接口不同平臺或風格的產品成組創建,創建“產品族”,產品之間有關聯性

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

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

相關文章

HTTP 與 HTTPS 深度解析:原理、實踐與大型項目應用

1. HTTP 與 HTTPS 基礎概念 1.1 HTTP&#xff08;超文本傳輸協議&#xff09; 定義&#xff1a;應用層協議&#xff0c;基于 TCP/IP 通信&#xff0c;默認端口 80 特點&#xff1a; 無狀態協議&#xff08;需 Cookie/Session 維護狀態&#xff09; 明文傳輸&#xff08;易被…

【Excel 擴展正則的能力】工作中賦予處理單元格文本的強大正則表達提取能力

文本提取處理領域&#xff0c;正則表達式是最為強大的存在&#xff0c;工作中Excel 是常用的小型數據采集&#xff0c;處理&#xff0c;分析的工具但本身不具備正則的能力&#xff0c;讓Excel擁有正則的能力無疑是如虎添翼的能力。 方案 讓正則作為函數內容的一部分&#xff0c…

rabbitmq 使用過程中遇到的問題

1. 連接rabbitmq 地址寫法&#xff0c;5672 是連接的端口號&#xff0c;15672是頁面訪問的端口號 2. elasticsearch 的訪問端口是9200&#xff0c; 不是9300&#xff0c;9300 是后臺通信端口號 &#xff0c;這個頁面訪問的端口號是一樣&#xff0c; 3. rabbitmq 的5種交換接…

HTML實戰:響應式個人資料頁面

我將創建一個現代化的響應式個人資料頁面,展示HTML在實際應用中的強大功能。這個頁面將包含多個實戰元素:導航欄、個人簡介、技能展示、作品集和聯系表單。 設計思路 使用Flexbox和Grid布局實現響應式設計 添加CSS過渡效果增強交互體驗 實現深色/淺色模式切換功能 創建懸停動…

工業自動化實戰:基于 VisionPro 與 C# 的機器視覺 PLC 集成方案

一、背景介紹 在智能制造領域&#xff0c;機器視覺檢測與 PLC 控制的無縫集成是實現自動化生產線閉環控制的關鍵。本文將詳細介紹如何使用 C# 開發上位機系統&#xff0c;實現 Cognex VisionPro 視覺系統與西門子 S7 PLC 的數據交互&#xff0c;打造高效、穩定的工業檢測方案。…

如何處理 Python 入門難以進步的現象

Python 初學者難以進步的根本原因在于&#xff1a;缺乏項目實踐、學習路徑不清晰、沒有掌握編程思維、忽略調試與源碼閱讀、缺乏系統性目標驅動。其中&#xff0c;“沒有項目驅動導致學習孤島效應”最為常見且致命。許多初學者只停留在語法知識、刷題階段&#xff0c;無法構建可…

【后端高階面經:緩存篇】37、高并發系統緩存性能優化:從本地到分布式的全鏈路設計

一、緩存性能優化的核心價值與分層架構 (一)緩存的多維價值體系 延遲優化 內存訪問速度(100ns) vs 磁盤數據庫(10ms+),性能提升10萬倍+案例:電商詳情頁通過緩存將響應時間從500ms降至50ms吞吐提升 單機Redis可支撐10萬QPS,分擔數據庫壓力案例:秒殺系統通過緩存攔截9…

windows本地虛擬機上運行docker-compose案例

1、先構建鏡像文件dockerfile&#xff0c;使用docker build -t redis-demo:1.0 -f dockerfile .來構建: FROM openjdk:8-jdk-alpineMAINTAINER qini<nqqq.com>VOLUME /data/upload_filesWORKDIR /usr/local/nqADD ./redis-demo.jar app.jarENV profile prod ENV timezon…

WPF布局基礎

開頭存一個快速排版插件 使用 XAML 格式化工具:XAML Styler - dino.c - 博客園 快捷鍵 在 Visual Studio 2022 中,輸入類似 <Button ... /> 的自閉合 XAML 標簽時,可以通過以下方式快速生成結尾的 />: 方法 1:輸入 / 自動補全 輸入標簽名和屬性: 輸入 <B…

Electron 桌面程序讀取dll動態庫

序幕&#xff1a;被GFW狙擊的第一次構建 當我在工位上輸入npm install electron時&#xff0c;控制臺跳出的紅色警報如同數字柏林墻上的一道彈痕&#xff1a; Error: connect ETIMEDOUT 104.20.22.46:443 網絡問題不用愁&#xff0c;請移步我的另外文章進行配置&#xff1a;…

javascript中運算符的優先級

優先級運算類型關聯性運算符19圓括號n/a( … )18成員訪問從左到右… . …Computed Member Access從左到右… [ … ]new (帶參數列表)n/anew … ( … )17函數調用從左到右… ( … )new (無參數列表)從右到左new …16后置遞增(運算符在后)n/a… 后置遞減(運算符在后)n/a… –15邏…

Linux的交換區

Linux 交換區&#xff08;Swap&#xff09;詳解 交換區&#xff08;Swap&#xff09;是 Linux 系統用于擴展內存的一種機制&#xff0c;它將部分磁盤空間虛擬成內存使用。當物理內存&#xff08;RAM&#xff09;不足時&#xff0c;系統會將不活躍的內存頁移動到交換區&#xf…

閱讀筆記——理解什么是LLM大語言模型

閱讀筆記&#xff1a; 理解LLM deepseek創新了什么 什么是多模態 什么是token ?? 定義??&#xff1a;Token是LLM處理文本的最小單位&#xff0c;相當于語言的"原子"??類比??&#xff1a; 中文&#xff1a;1個token ≈ 1個漢字或常見詞&#xff08;如"…

(自用)Java學習-5.14(注冊,鹽值加密,模糊查詢)

一、核心功能實現 1. 用戶注冊功能 前端實現 用戶名實時校驗&#xff1a;通過AJAX異步請求檢查用戶名是否已存在。 function checkName() {$.ajax({url: /users/checkUserName?uname uname,success: function(resp) {if (resp.code 200) alert("用戶名可用");el…

【雜談】STM32使用快速傅里葉變換庫函數后如何比較準確地找到n次諧波幅值

目錄 1.簡單介紹傅里葉變換的作用 2.諧波是什么 3.解決方法 1.簡單介紹傅里葉變換的作用 任何復雜的波形歸根結底都是由多個頻率和相位不一樣的正弦波組成的 通過傅里葉變換可以找到組成一個復雜的波形的所有正弦波的頻率和幅度信息 2.諧波是什么 假設有一個復雜的波形&a…

芯科科技推出首批第三代無線開發平臺SoC,高度集成的解決方案推動下一波物聯網實現突破

SiXG301和SiXG302是芯科科技采用22納米工藝節點推出的首批無線SoC系列產品&#xff0c;在計算能力、功效、集成度和安全性方面實現突破性進展 低功耗無線解決方案領導性創新廠商Silicon Labs&#xff08;亦稱“芯科科技”&#xff0c;NASDAQ&#xff1a;SLAB&#xff09;近日宣…

寫作即是生活

一個問題 “我是什么時候開始寫作的呢&#xff1f;”請你先暫停一下&#xff0c;別往下讀&#xff0c;先想想這個問題。 什么才是寫作&#xff1f; 或許在想上個問題之后&#xff0c;你就會開始想問另外一個問題&#xff0c;什么才算是寫作呢&#xff1f; 我的回答是&#x…

SpringBoot 執行Lua腳本 服務端執行 減少性能損耗 優化性能 優化連接性能

介紹 通過 Redis 執行 Lua 腳本時&#xff0c;所有的操作都在服務器端完成&#xff0c;而不是多次通過網絡進行請求。這可以顯著減少網絡延遲&#xff0c;尤其是在需要多次與 Redis 交互的場景中。多個操作可以在 Lua 腳本中組合成一個操作&#xff0c;而不是分多次請求&#…

Nginx代理、緩存與Rewrite

目錄 一、正向代理 &#xff08;一&#xff09;核心概念與應用場景 &#xff08;二&#xff09;Nginx正向代理編譯安裝&#xff08;以OpenEuler為例&#xff09; &#xff08;三&#xff09;驗證正向代理 二、反向代理 &#xff08;一&#xff09;七層代理&#xff08;HT…

PortSwigger-02-XXE

一&#xff1a;漏洞原理 1、XXE XXE全稱xml外部實體注入 XML&#xff1a;是一種用于標記電子文件使其具有結構性的標記語言&#xff0c;提供統一的方法來描述和交換獨立于應用程序或者供應商的結構化數據&#xff0c;它可以用來標記數據&#xff0c;定義數據類型、是一種允許…