c++注意點(12)----設計模式(生成器)

創建型模式

????????生成器模式(Builder Pattern)是一種創建型設計模式,它專注于將復雜對象的構建過程與表示分離,使得同樣的構建過程可以創建不同的表示。

? ? ? ? 就像是做飯,你可以自己慢慢做,各個步驟自己選擇。而使用生成器就像是預制菜,所有的最后菜的樣子,已經規劃好了。你只能從中選擇一個。

為什么需要生成器模式?

????????當我們需要創建具有復雜內部結構的對象(比如包含多個部件、構建步驟繁瑣或有多種配置方式的對象)時,直接在構造函數中處理會導致:

  • 構造函數參數過多,難以維護(比如創建一個 "電腦" 對象,需要指定 CPU、內存、硬盤、顯卡等十幾種參數);
  • 不同配置的對象需要不同的構建邏輯,導致代碼臃腫;
  • 構建過程與對象表示耦合,無法靈活切換不同的構建方式

舉個生活中的例子

想象你去電腦店組裝一臺電腦,整個過程其實很復雜:

  1. 需要選很多零件(CPU、內存、硬盤、顯卡等);
  2. 零件之間有搭配要求(比如主板要兼容 CPU);
  3. 組裝有固定步驟(先裝主板,再插 CPU,最后裝機箱);
  4. 不同需求選的零件不同(辦公用不需要好顯卡,游戲用需要大內存)。

如果沒有生成器模式,就像你自己去買零件、自己組裝:

  • 要記住所有零件型號和搭配規則,很容易出錯;
  • 每次換配置(比如從辦公電腦換成游戲電腦),都要重新學一遍選零件和組裝的流程;
  • 步驟錯了(比如先裝顯卡再裝主板),可能裝不上。

生成器模式就像請了一個專業裝機師傅(生成器)和一個客戶經理(指揮者):

  • 你只需要告訴客戶經理 “我要一臺辦公電腦”,不用管具體零件和步驟;
  • 裝機師傅知道所有零件搭配規則和組裝順序,會按步驟一步步裝好;
  • 想換游戲電腦?換一個擅長裝游戲電腦的師傅(另一個生成器)就行,你不用學新東西。

示例

#include <iostream>
#include <string>// 最終產品:電腦
class Computer {
private:std::string cpu_;       // 處理器std::string memory_;    // 內存std::string hardDisk_;  // 硬盤std::string graphics_;  // 顯卡std::string power_;     // 電源public:// 設置各部件(讓生成器可以修改內部屬性)void setCPU(const std::string& cpu) { cpu_ = cpu; }void setMemory(const std::string& memory) { memory_ = memory; }void setHardDisk(const std::string& hardDisk) { hardDisk_ = hardDisk; }void setGraphics(const std::string& graphics) { graphics_ = graphics; }void setPower(const std::string& power) { power_ = power; }// 獲取各部件信息std::string getCPU() const { return cpu_; }std::string getMemory() const { return memory_; }std::string getHardDisk() const { return hardDisk_; }std::string getGraphics() const { return graphics_; }std::string getPower() const { return power_; }// 顯示電腦配置void showConfig() const {std::cout << "電腦配置:\n";std::cout << "CPU:" << cpu_ << "\n";std::cout << "內存:" << memory_ << "\n";std::cout << "硬盤:" << hardDisk_ << "\n";std::cout << "顯卡:" << graphics_ << "\n";std::cout << "電源:" << power_ << "\n\n";}
};// 生成器接口(抽象類):定義組裝步驟
class Builder {
protected:Computer computer_;  // 正在組裝的電腦public:// 純虛函數:組裝各部件的步驟virtual void buildCPU() = 0;virtual void buildMemory() = 0;virtual void buildHardDisk() = 0;virtual void buildGraphics() = 0;virtual void buildPower() = 0;// 返回組裝好的電腦virtual Computer getComputer() {return computer_;}// 虛析構函數virtual ~Builder() = default;
};// 具體生成器1:辦公電腦生成器
class OfficeBuilder : public Builder {
public:void buildCPU() override {computer_.setCPU("英特爾 i5(入門級)");std::cout << "安裝辦公電腦CPU:" << computer_.getCPU() << "\n";}void buildMemory() override {computer_.setMemory("8G DDR4");std::cout << "安裝辦公電腦內存:" << computer_.getMemory() << "\n";}void buildHardDisk() override {computer_.setHardDisk("512G 固態硬盤");std::cout << "安裝辦公電腦硬盤:" << computer_.getHardDisk() << "\n";}void buildGraphics() override {computer_.setGraphics("集成顯卡");std::cout << "安裝辦公電腦顯卡:" << computer_.getGraphics() << "\n";}void buildPower() override {computer_.setPower("300W 電源");std::cout << "安裝辦公電腦電源:" << computer_.getPower() << "\n";}
};// 具體生成器2:游戲電腦生成器
class GameBuilder : public Builder {
public:void buildCPU() override {computer_.setCPU("英特爾 i7(高性能)");std::cout << "安裝游戲電腦CPU:" << computer_.getCPU() << "\n";}void buildMemory() override {computer_.setMemory("16G DDR5");std::cout << "安裝游戲電腦內存:" << computer_.getMemory() << "\n";}void buildHardDisk() override {computer_.setHardDisk("1T 固態硬盤");std::cout << "安裝游戲電腦硬盤:" << computer_.getHardDisk() << "\n";}void buildGraphics() override {computer_.setGraphics("RTX 4060 獨立顯卡");std::cout << "安裝游戲電腦顯卡:" << computer_.getGraphics() << "\n";}void buildPower() override {computer_.setPower("500W 電源");std::cout << "安裝游戲電腦電源:" << computer_.getPower() << "\n";}
};// 指揮者:負責控制組裝流程
class Director {
private:Builder* builder_;  // 指向當前使用的生成器public:// 構造函數:傳入生成器Director(Builder* builder) : builder_(builder) {}// 指揮組裝電腦(固定步驟)Computer construct() {std::cout << "開始組裝電腦...\n";builder_->buildCPU();builder_->buildMemory();builder_->buildHardDisk();builder_->buildGraphics();builder_->buildPower();std::cout << "組裝完成!\n\n";return builder_->getComputer();}
};// 客戶端:用戶購買電腦
int main() {// 1. 準備生成器(裝機師傅)OfficeBuilder officeBuilder;  // 辦公電腦裝機師傅GameBuilder gameBuilder;      // 游戲電腦裝機師傅// 2. 準備指揮者(客戶經理)Director director(nullptr);// 3. 組裝辦公電腦std::cout << "=== 組裝辦公電腦 ===\n";director = Director(&officeBuilder);  // 安排辦公裝機師傅Computer officeComputer = director.construct();  // 開始組裝officeComputer.showConfig();  // 查看配置// 4. 組裝游戲電腦std::cout << "=== 組裝游戲電腦 ===\n";director = Director(&gameBuilder);  // 換游戲裝機師傅Computer gameComputer = director.construct();  // 開始組裝gameComputer.showConfig();  // 查看配置return 0;
}

????????當然。有些參數是不一定使用的,可以選擇使用哪些。那么這里給出第二個示例,用于參考,額外的參數配置部分。

#include <iostream>
#include <string>
#include <vector>// 電腦產品(支持可選配件)
class Computer {
private:std::string cpu_;        // 必選:CPUstd::string memory_;     // 必選:內存std::string hardDisk_;   // 必選:硬盤std::string graphics_;   // 可選:顯卡(核顯/獨顯)std::string power_;      // 必選:電源std::vector<std::string> extras_; // 可選:額外配件(如散熱器、藍牙模塊)public:// 設置必選部件void setCPU(const std::string& cpu) { cpu_ = cpu; }void setMemory(const std::string& memory) { memory_ = memory; }void setHardDisk(const std::string& hardDisk) { hardDisk_ = hardDisk; }void setPower(const std::string& power) { power_ = power; }// 設置可選部件void setGraphics(const std::string& graphics) { graphics_ = graphics; }void addExtra(const std::string& extra) { extras_.push_back(extra); }// 獲取部件信息(用于生成器輸出)std::string getCPU() const { return cpu_; }std::string getMemory() const { return memory_; }std::string getHardDisk() const { return hardDisk_; }std::string getGraphics() const { return graphics_; }std::string getPower() const { return power_; }// 顯示配置(區分必選和可選)void showConfig() const {std::cout << "===== 電腦配置 =====" << "\n";std::cout << "【必選部件】\n";std::cout << "CPU:" << cpu_ << "\n";std::cout << "內存:" << memory_ << "\n";std::cout << "硬盤:" << hardDisk_ << "\n";std::cout << "電源:" << power_ << "\n";std::cout << "\n【可選部件】\n";std::cout << "顯卡:" << (graphics_.empty() ? "無(使用核顯)" : graphics_) << "\n";std::cout << "額外配件:";if (extras_.empty()) {std::cout << "無";}else {for (const auto& extra : extras_) {std::cout << extra << "、";}}std::cout << "\n====================\n\n";}
};// 生成器接口(支持可選步驟)
class Builder {
protected:Computer computer_;public:// 必選步驟(純虛函數,必須實現)virtual void buildCPU() = 0;virtual void buildMemory() = 0;virtual void buildHardDisk() = 0;virtual void buildPower() = 0;// 可選步驟(虛函數,默認空實現,可選擇性重寫)virtual void buildGraphics() {}  // 可選:裝獨立顯卡virtual void addExtra(const std::string& extra) {  // 可選:加配件computer_.addExtra(extra);}virtual Computer getComputer() { return computer_; }virtual ~Builder() = default;
};// 具體生成器1:極簡辦公電腦(不選獨顯,不加額外配件)
class MinimalOfficeBuilder : public Builder {
public:void buildCPU() override {computer_.setCPU("英特爾 i3(低功耗)");std::cout << "安裝CPU:" << computer_.getCPU() << "\n";}void buildMemory() override {computer_.setMemory("4G DDR4");std::cout << "安裝內存:" << computer_.getMemory() << "\n";}void buildHardDisk() override {computer_.setHardDisk("256G 固態硬盤");std::cout << "安裝硬盤:" << computer_.getHardDisk() << "\n";}void buildPower() override {computer_.setPower("200W 電源");std::cout << "安裝電源:" << computer_.getPower() << "\n";}// 不重寫buildGraphics(),使用默認空實現(不裝獨顯)// 不調用addExtra(),所以無額外配件
};// 具體生成器2:高端游戲電腦(選獨顯,加多個配件)
class HighEndGameBuilder : public Builder {
public:void buildCPU() override {computer_.setCPU("AMD Ryzen 9(旗艦級)");std::cout << "安裝CPU:" << computer_.getCPU() << "\n";}void buildMemory() override {computer_.setMemory("32G DDR5");std::cout << "安裝內存:" << computer_.getMemory() << "\n";}void buildHardDisk() override {computer_.setHardDisk("2T 固態硬盤");std::cout << "安裝硬盤:" << computer_.getHardDisk() << "\n";}void buildPower() override {computer_.setPower("800W 金牌電源");std::cout << "安裝電源:" << computer_.getPower() << "\n";}// 重寫可選步驟:安裝獨顯void buildGraphics() override {computer_.setGraphics("RTX 4090 獨顯");std::cout << "安裝顯卡:" << computer_.getGraphics() << "\n";}
};// 指揮者(支持靈活調整步驟)
class Director {
private:Builder* builder_;public:Director(Builder* builder) : builder_(builder) {}// 基礎組裝(只包含必選步驟)Computer buildBasic() {std::cout << "=== 開始基礎組裝(必選部件)===\n";builder_->buildCPU();builder_->buildMemory();builder_->buildHardDisk();builder_->buildPower();std::cout << "基礎組裝完成!\n";return builder_->getComputer();}// 完整組裝(必選+可選步驟)Computer buildComplete() {std::cout << "\n=== 開始完整組裝(必選+可選)===\n";Computer basic = buildBasic();  // 復用基礎組裝邏輯builder_->buildGraphics();      // 可選:裝顯卡builder_->addExtra("水冷散熱器"); // 可選:加配件builder_->addExtra("藍牙模塊");   // 可選:加配件std::cout << "完整組裝完成!\n";return builder_->getComputer();}
};// 客戶端:靈活定制不同配置
int main() {// 1. 組裝極簡辦公電腦(只裝必選部件)MinimalOfficeBuilder officeBuilder;Director officeDirector(&officeBuilder);Computer officePC = officeDirector.buildBasic();  // 只調用必選步驟officePC.showConfig();// 2. 組裝高端游戲電腦(必選+可選部件)HighEndGameBuilder gameBuilder;Director gameDirector(&gameBuilder);Computer gamePC = gameDirector.buildComplete();  // 調用必選+可選步驟gamePC.showConfig();// 3. 臨時加配件(生成器模式支持中途調整)std::cout << "給辦公電腦臨時加一個配件:\n";officeBuilder.addExtra("無線網卡");officePC = officeBuilder.getComputer();officePC.showConfig();return 0;
}

優勢

????????1.使用生成器模式可避免?“重疊構造函數?(telescoping constructor)”?的出現。

?????????假設你的構造函數中有十個可選參數,?那么調用該函數會非常不方便;?因此,?你需要重載這個構造函數,?新建幾個只有較少參數的簡化版。?但這些構造函數仍需調用主構造函數,?傳遞一些默認數值來替代省略掉的參數。

class Pizza {Pizza(int size) { …… }Pizza(int size, boolean cheese) { …… }Pizza(int size, boolean cheese, boolean pepperoni) { …… }
//............

????????生成器模式讓你可以分步驟生成對象,?而且允許你僅使用必須的步驟。?應用該模式后,?你再也不需要將幾十個參數塞進構造函數里了。

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

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

相關文章

[特殊字符] VLA 如何“繞過”手眼標定?—— 當機器人學會了“看一眼就動手”

&#x1f52e; VLA 如何“繞過”手眼標定&#xff1f;—— 當機器人學會了“看一眼就動手” 作者&#xff1a;石去皿 發布時間&#xff1a;2025年7月 在傳統機器人系統中&#xff0c;“手眼標定”是每一個工程師都繞不開的課題。 你必須精確測量相機和機械臂之間的空間變換關系…

《Maven 核心基礎筆記(第一天)》

1.說明maven軟件依賴管理和項目構建功能maven是為Java項目工作的 功能體現&#xff1a;依賴管理&#xff0c;項目構建 依賴管理&#xff1a;我們只需要寫配置文件(pom.xml)&#xff0c;maven就會幫我們下載依賴&#xff0c;并且也會下載依賴的依賴。 項目構建&#xff1a;項目源…

Yolo底層原理學習(V1~V3)(第一篇)

一&#xff0c;卷積后的特征圖大小計算眾所周知&#xff0c;提到深度學習&#xff0c;必不可少的會提及卷積&#xff0c;那么如何計算卷積之后的圖片大小呢&#xff1f;下圖呈現&#xff1a;如圖&#xff0c; 我們令FH&#xff0c;FW為原圖像的長度FH*FW。P為padding的長度&…

前端開發項目性能瓶頸分析

1. 使用 rollup-plugin-visualizer 分析構建 借助 rollup-plugin-visualizer 插件&#xff0c;可以分析通過 rollup 構建出的產物內容&#xff0c;并生成可視化圖表&#xff0c;幫助你分析打包后的文件大小以及各個模塊的占用情況。 1.1. 安裝插件 你需要在你的項目中安裝 r…

ExoData.h - OpenExo

ExoData.h文件定位源代碼1. 頭文件依賴2. 核心類聲明3. 主要成員函數關節遍歷工具關節與配置相關數據/狀態操作控制參數/校準4. 主要成員變量總結文件定位 位置&#xff1a;src/ExoData.h 作用&#xff1a;定義 ExoData 類&#xff0c;作為 Exo 系統全局數據的核心容器。它將設…

緩存HDC內容用于后續Direct2D繪制.

思路&#xff1a;把HDC里的內容保存到Direct2D格式的位圖里&#xff0c;后續直接調用 renderTarget->DrawBitmap即可。本例中&#xff0c;位圖將保存為類的字段。本例中 COM 接口指針皆使用 com_ptr&#xff0c;這是 WinRT 的 COM 智能指針類&#xff0c;com_ptr<I>::…

“抓了個寂寞”:一次實時信息采集的意外和修復

1. 那天下午&#xff0c;輿情系統“遲到”了 那天下午&#xff0c;公司運營那邊突然在群里喊&#xff1a;“XX事件都快上熱搜榜前十了&#xff0c;咱們系統咋沒反應&#xff1f;” 我愣了幾秒&#xff0c;立馬翻后臺日志、爬蟲執行記錄&#xff0c;結果一查&#xff0c;還真有點…

數據結構之迪杰斯特拉算法

前言&#xff1a;前面兩篇文章介紹了生成圖的最小生成樹的算法&#xff0c;接下來兩篇文章會介紹圖的最短路徑的算法&#xff0c;迪杰斯特拉算法和弗洛伊德算法。迪杰斯特拉算法是用來計算一個點到其他所有點的最短路徑&#xff0c;這個點稱之為源點。 一、實現流程 回憶一下…

技術文檔 | OpenAI 的 Kafka 演進之路與 Pulsar 遷移潛力

導讀ChatGPT 用戶量指數級暴漲&#xff0c;OpenAI 的 Kafka 集群在一年內增長 20 倍至 30 個集群[1]&#xff0c;其 Kafka 架構面臨日均千億級消息&#xff08;峰值 QPS 800萬/秒&#xff09; 的壓力。這揭示了一個關鍵事實&#xff1a;OpenAI 的成功不只依賴模型&#xff0c;更…

【bug】 jetson上opencv無法錄制h264本地視頻

在Jetson Orin NX上無法使用opencv直接錄制h264/h265視頻流&#xff08;h264格式的視頻流才能在瀏覽器播放&#xff09; 解決&#xff1a; 軟件編碼&#xff1a;需要源碼編譯opencv 1.環境準備 pip uninstall opencv-python sudo apt install build-essential cmake git python…

解決http的web服務中與https服務交互的問題

問題背景&#xff1a; 需要在一個http的web服務中直接跟另一個https服務交互&#xff0c;不經過自身后端。 又來到了熟悉的跨域訪問問題。 解決邏輯就是使用nginx轉發&#xff0c;涉及到的文件也就是nginx.conf文件&#xff0c;前面解決minio鏈接時已經有經驗了&#xff0c;但…

網站訪問信息追蹤系統在安全與性能優化中的關鍵作用——網絡安全—仙盟創夢IDE

<?php // 收集訪問信息 $visitorInfo未來之窗 [timestamp > date(Y-m-d H:i:s),ip > $_SERVER[REMOTE_ADDR] ?? unknown,page > $_SERVER[REQUEST_URI] ?? unknown,method > $_SERVER[REQUEST_METHOD] ?? unknown,user_agent > $_SERVER[HTTP_USER_A…

Oracle 時間處理函數和操作符筆記

前言 寫sql時經常用到時間處理函數&#xff0c;我整理了一份Oracle的常用sql筆記,供大家參考。 如果對你有幫助&#xff0c;請點贊支持~ 多謝&#x1f64f; 筆記 -- 1. 獲取當前日期和時間 -- SYSDATE, SYSTIMESTAMP, CURRENT_DATE, CURRENT_TIMESTAMP, LOCALTIMESTAMP SELE…

TDengine時序數據庫 詳解

1. TDengine 簡介 TDengine 是一款 高性能、分布式、支持 SQL 的時序數據庫&#xff08;Time-Series Database, TSDB&#xff09;&#xff0c;專為 物聯網&#xff08;IoT&#xff09;、工業互聯網、金融監控、日志分析 等場景設計。其核心特點包括&#xff1a; 超高性能&…

【IDEA】idea怎么修改注冊的用戶名稱?

文章目錄[toc]問題**方法 1&#xff1a;通過 JetBrains 賬戶網站修改****方法 2&#xff1a;通過 IDEA 內跳轉修改&#xff08;快捷方式&#xff09;****注意事項****補充&#xff1a;修改 IDEA 內的項目級用戶名**如何退出IDEA用戶登錄&#xff1f;問題 在 IntelliJ IDEA 中修…

AR眼鏡重塑外科手術導航:精準“透視”新突破

在現代醫學領域&#xff0c;增強現實&#xff08;AR www.teamhelper.cn &#xff09;技術正以前所未有的方式改變外科手術導航的面貌。通過為醫生提供實時的三維可視化、精準的空間定位和智能交互功能&#xff0c;AR眼鏡正在成為手術室中的重要工具。本文將系統介紹AR眼鏡在手術…

服務端對接 HTTP 接口傳輸圖片 采用base64還是 multipart/form-data

在服務端對接HTTP接口傳輸圖片時&#xff0c;選擇 multipart/form-data 還是 Base64 編碼&#xff0c;需要根據具體場景權衡。以下是詳細對比和建議&#xff1a;1. multipart/form-data 優點 更適合大文件傳輸&#xff1a; 直接以二進制流傳輸圖片&#xff0c;無需編碼/解碼&am…

如何在 Windows 上安裝 MongoDB 及常見問題

MongoDB 是一款 NoSQL 數據庫&#xff0c;在數據管理和存儲方面以其無與倫比的強大功能和多功能性而脫穎而出。該平臺憑借其靈活性、可擴展性和高性能保持著領先優勢&#xff0c;贏得了眾多企業的信賴。在這方面&#xff0c;MongoDB 以及其在 Windows 操作系統中的表現&#xf…

JS與Go:編程語言雙星的碰撞與共生

在編程語言的璀璨星河中&#xff0c;JavaScript&#xff08;簡稱JS&#xff09;與Go語言憑借各自獨特的魅力&#xff0c;成為不同領域的佼佼者。前者以靈活多變的姿態征服了前端世界&#xff0c;后者則以高效穩健的特性在后端領域嶄露頭角&#xff0c;二者的碰撞與共生&#xf…

【開源】WpfMap:一個基于WPF(Windows Presentation Foundation)技術構建的數據可視化大屏展示頁面

文章目錄一、項目概述1.1 項目定位二、適用場景2.1 企業數據展示2.2 監控中心2.3 會議展示三、功能特性3.1 高度自定義3.2 實時更新3.3 豐富的可視化組件3.4 良好的用戶體驗四、技術資源4.1 開源地址一、項目概述 1.1 項目定位 WpfMap是一個基于WPF&#xff08;Windows Prese…