突破編程_C++_設計模式(建造者模式)

1 建造者模式的概念

建造者模式(Builder Pattern)是一種創建型設計模式,也被稱為生成器模式。它的核心思想是將一個復雜對象的構建與它的表示分離,使得同樣的構建過程可以創建不同的表示。

在建造者模式中,通常包括以下幾個角色:

(1)Builder: 這是一個抽象接口,定義了產品對象的各個組成成分的建造。它規定了要實現復雜對象的哪些部分的創建,但并不涉及具體的對象部件的創建。
(2)ConcreteBuilder: 這是實現了Builder接口的具體類,它針對不同的商業邏輯,具體化了復雜對象的各部分的創建。在建造過程完成后,它提供產品的實例。
(3)Director: 這是一個指揮者角色,它調用具體建造者來創建復雜對象的各個部分。在指導者中,不涉及具體產品的信息,只負責保證對象各部分完整創建或按某種順序創建。
(4)Product: 這是最終要創建的復雜對象。

建造者模式允許用戶只通過指定復雜對象的類型和內容來構建對象,而不需要知道內部的具體構建細節。這種模式特別適用于構建具有多個組成部分的復雜對象,且這些組成部分的構建過程可能會因具體需求而有所不同的情況。通過建造者模式,可以使得同樣的構建過程能夠創建出不同的產品表示,提高了系統的靈活性和可擴展性。

1.1 建造者模式的應用場景

建造者模式通常適用于以下應用場景:

(1)對象結構復雜: 當需要創建的對象具有復雜的內部結構,包含多個組件或屬性時,可以使用建造者模式來構建這些對象。通過將構建過程分解為多個步驟,可以更加清晰地管理和控制對象的創建過程。
(2)創建流程固定: 當對象的創建流程是固定的,即無論創建多少個對象,其構建步驟都是相同的時候,可以使用建造者模式。通過將這些步驟封裝在建造者類中,可以確保每次創建對象時都遵循相同的流程。
(3)需要控制創建過程: 當需要更加靈活地控制對象的創建過程,例如根據用戶輸入或運行時條件來決定對象的某些屬性時,可以使用建造者模式。通過在指揮者類中引入邏輯來控制對象的創建,可以實現更加靈活的構建過程。
(4)代碼易于閱讀和維護: 當需要創建的對象具有大量的參數或配置選項時,使用建造者模式可以將這些參數和選項分組并封裝在不同的建造者類中,從而減少構造函數的復雜度,使代碼更加易讀和易于維護。

在實際應用中,建造者模式常用于構建具有多個組件或屬性的復雜對象,如UI界面、配置文件、數據庫查詢結果等。通過使用建造者模式,可以更加清晰地組織代碼,提高代碼的可讀性和可維護性,同時降低對象創建的復雜性。

1.2 建造者模式的優點和缺點

建造者模式的優點主要包括:

(1)封裝性好: 建造者模式將對象的構建與它的表示分離,使得客戶端不必知道產品內部組成的細節,隱藏了產品的內部實現細節,提供了更好的封裝性。
(2)擴展性好: 由于具體的建造者是相互獨立的,因此易于擴展。如果需要增加新的部件或修改現有部件的創建方式,只需要增加或修改相應的建造者類,而不會影響其他已構建的部件和客戶端代碼。
(3)控制細節風險: 建造者模式允許對創建過程逐步細化,而不對其他模塊產生任何影響,便于控制細節風險。客戶端只需要指定需要構建的對象類型和內容,而不需要了解具體的構建細節,從而降低了客戶端代碼的復雜性。

然而,建造者模式也存在一些缺點:

(1)使用范圍受限: 建造者模式所創建的產品一般具有較多的共同點,其組成部分相似。如果產品之間的差異性很大,例如很多組成部分都不相同,不適合使用建造者模式,因此其使用范圍受到一定的限制。
(2)可能導致系統龐大: 如果產品的內部變化復雜,可能需要定義很多具體建造者類來實現這種變化,導致系統變得很龐大。這會增加系統的理解難度和運行成本,因為需要維護大量的建造者類。

綜上所述,建造者模式在創建具有復雜內部結構和多個組件的對象時非常有用,可以提供良好的封裝性、擴展性和對細節的控制。然而,它也有一些限制,特別是在產品差異性大或內部變化復雜的情況下。因此,在使用建造者模式時需要權衡其優點和缺點,并根據具體的應用場景做出決策。

2 建造者模式的實現步驟

本章節使用一個建造房子的樣例來講解建造者模式的實現步驟。

2.1 定義產品(Product)類

首先,定義 Product 類,它表示最終要構建的對象。在本章節的例子中,構建一個 House 類:

#include <iostream>  
#include <memory>  
#include <string>  class House 
{
public:void setWalls(const std::string& walls) {this->walls = walls;}void setRoof(const std::string& roof) {this->roof = roof;}void setFloors(const std::string& floors) {this->floors = floors;}void showHouseDetails() const {std::cout << "Walls: " << walls << std::endl;std::cout << "Roof: " << roof << std::endl;std::cout << "Floors: " << floors << std::endl;}private:std::string walls;std::string roof;std::string floors;
};

2.2 定義抽象建造者(Builder)接口

接下來,定義一個 Builder 抽象接口,它聲明了構建 House 對象所需的方法:

class HouseBuilder 
{
public:virtual ~HouseBuilder() = default;virtual void buildWalls() = 0;virtual void buildRoof() = 0;virtual void buildFloors() = 0;virtual std::shared_ptr<House> getHouse() = 0;
};

2.3 定義具體建造者(ConcreteBuilder)類

然后,創建實現 HouseBuilder 接口的 ConcreteBuilder 類。這個類將包含構建 House 對象所需的具體實現:

class ConcreteHouseBuilder : public HouseBuilder 
{
public:ConcreteHouseBuilder() : house(std::make_shared<House>()) {}void buildWalls() override {house->setWalls("Concrete walls");}void buildRoof() override {house->setRoof("Concrete roof");}void buildFloors() override {house->setFloors("Concrete floors");}std::shared_ptr<House> getHouse() override{return std::move(house);}private:std::shared_ptr<House> house;
};

2.4 定義指揮者(Director)類

接下來,創建一個 Director 類,它負責指揮 Builder 對象來構建 Product 對象:

class HouseDirector 
{
public:HouseDirector(std::shared_ptr<HouseBuilder> builder) : builder(builder) {}void constructHouse() {builder->buildWalls();builder->buildRoof();builder->buildFloors();}std::shared_ptr<House> getHouse(){return builder->getHouse();}private:std::shared_ptr<HouseBuilder> builder;};

2.5 客戶端使用

最后,在 main 函數中,使用這些類來構建 House 對象:

int main() 
{// 創建具體建造者對象  auto builder = std::make_shared<ConcreteHouseBuilder>();// 創建指揮者對象,并將建造者傳遞給指揮者  HouseDirector director(builder);// 通過指揮者構建產品  director.constructHouse();// 獲取并顯示構建好的產品  auto house = director.getHouse();house->showHouseDetails();return 0;
}

上面代碼的輸出為:

Walls: Concrete walls
Roof: Concrete roof
Floors: Concrete floors

在上面代碼中,使用 std::make_shared 來創建 ConcreteHouseBuilder 對象,并將其傳遞給 HouseDirector 。HouseDirector 通過調用 concreteHouseBuilder 的方法逐步構建了一個 House 對象,并通過 getHouse 方法返回了 House 對象的所有權。最后,獲取這個構建好的 House 對象,并顯示其對象細節。

3 建造者模式的案例解析

3.1 對象結構復雜場景下使用建造者模式

如下的樣例將展示如何使用建造者模式來構建一個 Computer 對象,其中包含 Processor 和 Memory 兩個子組件(為了簡化代碼,實際一個電腦的子組件會很多)。

首先,定義各個子組件以及 Computer 類:

#include <iostream>  
#include <memory>  
#include <string>  // 子組件類  
class Processor 
{
public:void setSpeed(int speed) { m_speed = speed; }void setCores(int cores) { m_cores = cores; }void showDetails() const {std::cout << "Processor: " << m_speed << " MHz, " << m_cores << " cores" << std::endl;}private:int m_speed;int m_cores;
};class Memory 
{
public:void setSize(int size) { m_size = size; }void setType(const std::string& type) { m_type = type; }void showDetails() const {std::cout << "Memory: " << m_size << " GB, " << m_type << " RAM" << std::endl;}private:int m_size;std::string m_type;
};// 產品類  
class Computer {
public:void setProcessor(std::shared_ptr<Processor> processor) { m_processor = processor; }void setMemory(std::shared_ptr<Memory> memory) { m_memory = memory; }void showDetails() const {m_processor->showDetails();m_memory->showDetails();}private:std::shared_ptr<Processor> m_processor;std::shared_ptr<Memory> m_memory;
};

接下來,定義抽象建造者接口和具體的建造者類:

// 產品類  
class Computer {
public:void setProcessor(std::shared_ptr<Processor> processor) { m_processor = processor; }void setMemory(std::shared_ptr<Memory> memory) { m_memory = memory; }void showDetails() const {m_processor->showDetails();m_memory->showDetails();}private:std::shared_ptr<Processor> m_processor;std::shared_ptr<Memory> m_memory;
};// 抽象建造者接口  
class ComputerBuilder 
{
public:virtual ~ComputerBuilder() = default;virtual void buildProcessor() = 0;virtual void buildMemory() = 0;virtual std::shared_ptr<Computer> getComputer() = 0;
};// 具體建造者類  
class GamingComputerBuilder : public ComputerBuilder 
{
public:GamingComputerBuilder() : m_computer(std::make_shared<Computer>()) {m_processor = std::make_shared<Processor>();m_memory = std::make_shared<Memory>();}void buildProcessor() override {m_processor->setSpeed(3500);m_processor->setCores(6);}void buildMemory() override {m_memory->setSize(16);m_memory->setType("DDR4");}std::shared_ptr<Computer> getComputer() override {m_computer->setProcessor(m_processor);m_computer->setMemory(m_memory);return m_computer;}private:std::shared_ptr<Computer> m_computer;std::shared_ptr<Processor> m_processor;std::shared_ptr<Memory> m_memory;
};

然后,定義 Director 類,負責指導 Builder 對象如何構建最終的產品:

class Director 
{
public:Director(std::shared_ptr<ComputerBuilder> builder) : m_builder(builder) {}void constructComputer() {m_builder->buildProcessor();m_builder->buildMemory();}std::shared_ptr<Computer> getComputer() {return m_builder->getComputer();}private:std::shared_ptr<ComputerBuilder> m_builder;
};

最后,在 main 函數中使用 Director 和 GamingComputerBuilder 來構建一個 Computer 對象:

int main() 
{// 創建具體的建造者對象  std::shared_ptr<ComputerBuilder> builder = std::make_shared<GamingComputerBuilder>();// 創建導演對象,并將建造者對象傳遞給它  Director director(builder);// 指導構建過程  director.constructComputer();// 獲取構建好的產品  std::shared_ptr<Computer> computer = director.getComputer();// 展示產品詳情  computer->showDetails();return 0;
}

上面代碼的輸出為:

Processor: 3500 MHz, 6 cores
Memory: 16 GB, DDR4 RAM

3.2 對象結構復雜場景下使用建造者模式

在創建流程固定的場景下,可以使用一個簡單的 Builder 類來封裝一個固定流程的構建過程。這種場景下,Builder 類會提供一系列的方法來逐步構建對象,并最終提供一個方法來獲取構建好的對象。客戶端代碼則直接調用 Builder 的方法來構建對象。
如下為樣例代碼:

#include <iostream>  
#include <memory>  
#include <string>  // 產品類  
class Product 
{
public:void show() const {std::cout << "Product built with parts: " << partA << ", " << partB << ", " << partC << std::endl;}public:std::string partA;std::string partB;std::string partC;
};// 建造者類  
class Builder 
{
public:Builder() { m_product = std::make_shared<Product>(); }// 初始化產品  void setPartA(const std::string& partA) { m_product->partA = partA; }void setPartB(const std::string& partB) { m_product->partB = partB; }void setPartC(const std::string& partC) { m_product->partC = partC; }// 構建并返回產品  std::shared_ptr<Product> build() {// 在這里可以添加一些額外的構建邏輯return m_product;}private:std::shared_ptr<Product> m_product;
};int main() 
{// 創建建造者對象  Builder builder;// 通過建造者設置產品的各個部分  builder.setPartA("Part A content");builder.setPartB("Part B content");builder.setPartC("Part C content");// 構建并獲取產品  auto product = builder.build();// 展示產品  product->show();return 0;
}

上面代碼的輸出為:

Product built with parts: Part A content, Part B content, Part C content

在上面代碼中,Product 類是一個簡單的產品類,包含三個私有成員變量。Builder 類封裝了 Product 對象的構建過程,它提供了三個方法來設置產品的各個部分,以及一個 Build 方法來構建并返回產品對象。

在 main 函數中,客戶端代碼創建了 Builder 對象,并通過調用 setPartA、setPartB 和 setPartC 方法來設置產品的各個部分。然后,調用 Build 方法來構建產品對象,并存儲在 std::shared_ptr 中。最后,調用Show方法來展示構建好的產品。

上面代碼展示了如何在創建流程固定的情況下使用建造者模式。Builder 類確保了產品總是按照相同的步驟和順序被構建,而客戶端代碼則不需要了解具體的構建細節。這有助于保持代碼的清晰和易于維護。

4 建造者模式與工廠模式的比較

建造者模式和工廠模式都是面向對象設計模式中常用的創建型模式,它們的主要區別在于關注點、對象創建過程以及復雜度。

關注點: 工廠模式主要關注對象的創建,而建造者模式不僅關注對象的創建,還關注對象的組成部分以及這些部分的構建順序。
對象創建過程: 工廠模式通常提供一個統一的接口來創建對象,而不需要知道具體創建對象的類。而建造者模式則更加關注對象的構建過程,它允許用戶逐步添加對象的各個部分,并控制這些部分的構建順序。
復雜度: 工廠模式通常用于創建簡單對象,而建造者模式更適合用于創建復雜對象。建造者模式允許用戶將復雜對象的構建過程分解為多個步驟,每個步驟只關注對象的一個或幾個部分,從而降低了構建過程的復雜度。

總的來說,工廠模式和建造者模式都是用于創建對象的模式,但它們在關注點、對象創建過程以及復雜度上有所不同。選擇哪種模式取決于具體的應用場景和需求。

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

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

相關文章

MySQL進階:MySQL事務、并發事務問題及隔離級別

&#x1f468;?&#x1f393;作者簡介&#xff1a;一位大四、研0學生&#xff0c;正在努力準備大四暑假的實習、 &#x1f30c;上期文章&#xff1a;MySQL進階&#xff1a;視圖&&存儲過程&&存儲函數&&觸發器 &#x1f4da;訂閱專欄&#xff1a;MySQL進…

Docker Machine windows系統下 安裝

如果你是 Windows 平臺&#xff0c;可以使用 Git BASH&#xff0c;并輸入以下命令&#xff1a; basehttps://github.com/docker/machine/releases/download/v0.16.0 &&mkdir -p "$HOME/bin" &&curl -L $base/docker-machine-Windows-x86_64.exe >…

點燃技能火花:探索PyTorch學習網站,開啟AI編程之旅!

介紹&#xff1a;PyTorch是一個開源的Python機器學習庫&#xff0c;它基于Torch&#xff0c;專為深度學習和科學計算而設計&#xff0c;特別適合于自然語言處理等應用程序。以下是對PyTorch的詳細介紹&#xff1a; 歷史背景&#xff1a;PyTorch起源于Torch&#xff0c;一個用于…

【真機Bug】異步加載資源未完成訪問單例導致資源創建失敗

1.錯誤表現描述 抽卡時&#xff0c;10抽展示界面為A。抽取內容可能是整卡或者碎片&#xff0c;抽到整卡&#xff0c;會有立繪展示和點擊詳情的按鈕。點擊詳情后出現詳情頁B。【此時界面A預制體被銷毀&#xff0c;卡片數據進入數據緩存池】點擊頁面B的返回按鈕&#xff0c;單例…

C++——模版

前言&#xff1a;哈嘍小伙伴們好久不見&#xff0c;這是2024年的第一篇博文&#xff0c;我們將繼續C的學習&#xff0c;今天這篇文章&#xff0c;我們來習一下——模版。 目錄 一.什么是模版 二.模版分類 1.函數模版 2.類模板 總結 一.什么是模版 說起模版&#xff0c;我們…

線索二叉樹

線索二叉樹即從前、中、后序三種遍歷中其中一種來看&#xff0c;樹中的左右孩子都不會是空著的&#xff0c;都會指向對應的前驅和后驅。 以中序遍歷為例&#xff0c;二叉樹線索化過程如下&#xff1a; 先是樹的結構 typedef struct ThreadNode{Elemetype data;struct ThreadNo…

微服務面試題之套路一

面試題 一、你的項目是從SpringBoot演進到微服務架構的&#xff0c;你在此過程中有調研過哪些技術&#xff0c;怎么調研落地的? 微服務通信框架&#xff1a; 需要選擇適合項目的微服務通信框架&#xff0c;如Dubbo、Spring Cloud或gRPC Feign RestTemplate 等。調研方式可以是…

高性能通信之Netty

一, 同步IO(BIO)模型的架構 一般針對性能不高的情況下可以使用. 二,異步IO(NIO)模型的架構 多路復用(epoll模型):

【LeetCode:124. 二叉樹中的最大路徑和 + 二叉樹+遞歸】

&#x1f680; 算法題 &#x1f680; &#x1f332; 算法刷題專欄 | 面試必備算法 | 面試高頻算法 &#x1f340; &#x1f332; 越難的東西,越要努力堅持&#xff0c;因為它具有很高的價值&#xff0c;算法就是這樣? &#x1f332; 作者簡介&#xff1a;碩風和煒&#xff0c;…

前端開發人員如何做好SEO

前端開發人員如何做好SEO SEO工作不僅限于專業人員。前端開發者也可以在日常開發中實施一些代碼層面的SEO優化。 以下是一些前端常用的SEO方法&#xff1a; 設置合理的title、keywords、description title、keywords、description對SEO至關重要&#xff0c;需貼合頁面內容編…

Codeforces Round 931 (Div. 2) (A~B)

比賽&#xff1a;Codeforces Round 931 (Div. 2) (A~B) 目錄&#xff1a;A B A題&#xff1a;Too Min Too Max 標簽: 構造算法&#xff08;constructive algorithms&#xff09;貪心&#xff08;greedy&#xff09;數學&#xff08;math&#xff09; 題目大意 對數組 a 找到…

【力扣hot100】刷題筆記Day19

前言 回溯回溯回溯&#xff01;早上整理檔案竟然用了桶排序&#xff0c;不愧是算法狂魔們 79. 單詞搜索 - 力扣&#xff08;LeetCode&#xff09; DFS class Solution:def exist(self, board: List[List[str]], word: str) -> bool:m, n len(board), len(board[0])# used…

mysql timestamp轉換為datetime

MySQL timestamp轉換為datetime的方法 1. 流程概述 在MySQL中&#xff0c;timestamp和datetime是兩種不同的數據類型。timestamp存儲了日期和時間&#xff0c;并且會自動更新&#xff0c;可以用于記錄數據的創建和修改時間。datetime則是一個固定的日期和時間&#xff0c;不會自…

談談高并發系統的設計方法論

談談高并發系統的設計方法論 何為高并發系統&#xff1f;什么是并發&#xff08;Conurrent&#xff09;&#xff1f;什么是高并發&#xff08;Hight Concurrnet&#xff09;&#xff1f;高并發的衡量指標有哪些&#xff1f; 實現高并發系統的兩大板塊高并發系統應用程序側的設計…

騰訊云學生服務器使用教程_申請騰訊云學生機詳細流程

2024年騰訊云學生服務器優惠活動「云校園」&#xff0c;學生服務器優惠價格&#xff1a;輕量應用服務器2核2G學生價30元3個月、58元6個月、112元一年&#xff0c;輕量應用服務器4核8G配置191.1元3個月、352.8元6個月、646.8元一年&#xff0c;CVM云服務器2核4G配置842.4元一年&…

還在用Jenkins?快來試試這款簡而輕的自動部署軟件!

最近發現了一個比 Jenkins 使用更簡單的項目構建和部署工具&#xff0c;完全可以滿足個人以及一些小企業的需求&#xff0c;分享一下。 Jpom 是一款 Java 開發的簡單輕量的低侵入式在線構建、自動部署、日常運維、項目監控軟件。 日常開發中&#xff0c;Jpom 可以解決下面這些…

Nginx的多線程支持探究

文章中心思想: Nginx本身并不直接支持多線程處理模型。它采用的是基于事件驅動的單線程或多進程架構,而非多線程模型。然而,通過Nginx的模塊和第三方擴展,可以實現類似多線程的并發處理效果。 詳細說明: Nginx,作為一款高性能的Web服務器和反向代理服務器,其架構和并發…

章節二、three.js開發入門與調試設置02;

一、軌道控制器查看物體&#xff1b; 1、基本概念 軌道控制器&#xff08;OrbitControls&#xff09;可以使得相機圍繞目標進行軌道運動&#xff1b; 2、代碼樣例 // 七、創建軌道控制器&#xff08;相機圍繞著物體捕捉視角&#xff09; const controls new OrbitControls(c…

吳恩達機器學習全課程筆記第五篇

目錄 前言 P80-P85 添加數據 遷移學習 機器學習項目的完整周期 公平、偏見與倫理 P86-P95 傾斜數據集的誤差指標 決策樹模型 測量純度 選擇拆分方式增益 使用分類特征的一種獨熱編碼 連續的有價值特征 回歸樹 前言 這是吳恩達機器學習筆記的第五篇&#xff0c…

《2023跨境電商投訴大數據報告》發布|亞馬遜 天貓國際 考拉海購 敦煌網 阿里巴巴

2023年&#xff0c;跨境電商API接口天貓國際、京東國際和抖音全球購以其強大的品牌影響力和市場占有率&#xff0c;穩坐行業前三的位置。同時&#xff0c;各大跨境電商平臺消費糾紛問題層出不窮。依據國內知名網絡消費糾紛調解平臺“電訴寶”&#xff08;315.100EC.CN&#xff…