【C++设计模式】第四篇:建造者模式(Builder)

news2025/3/10 7:45:57

注意:复现代码时,确保 VS2022 使用 C++17/20 标准以支持现代特性。

分步骤构造复杂对象,实现灵活装配


1. 模式定义与用途

核心目标:将复杂对象的构建过程分离,使得同样的构建步骤可以创建不同的表示形式。
常见场景

  • 创建包含多个组件的复杂对象(如游戏角色、文档格式)
  • 需要逐步构造对象,并支持不同配置选项
  • 避免构造函数参数爆炸(尤其是可选参数众多时)

2. 模式结构解析

在这里插入图片描述

  • Builder:定义构造步骤的抽象接口(如 buildHead(), buildBody()
  • ConcreteBuilder:实现具体构造逻辑,提供获取结果的接口
  • Director:控制构造流程(可选,可让客户端直接操作Builder)
  • Product:最终构造的复杂对象

3. 现代 C++ 实现示例:游戏角色构造

3.1 基础实现

#include <iostream>
#include <memory>
#include <string>

// 产品:游戏角色
class GameCharacter {
public:
    void setHead(const std::string& head) { head_ = head; }
    void setBody(const std::string& body) { body_ = body; }
    void setWeapon(const std::string& weapon) { weapon_ = weapon; }

    void describe() const {
        std::cout << "Character: " << head_ << ", " << body_ 
                  << ", wielding " << weapon_ << "\n";
    }

private:
    std::string head_;
    std::string body_;
    std::string weapon_;
};

// 抽象建造者
class CharacterBuilder {
public:
    virtual ~CharacterBuilder() = default;
    virtual void buildHead() = 0;
    virtual void buildBody() = 0;
    virtual void buildWeapon() = 0;
    virtual std::unique_ptr<GameCharacter> getResult() = 0;
};

// 具体建造者:骑士
class KnightBuilder : public CharacterBuilder {
public:
    KnightBuilder() { character_ = std::make_unique<GameCharacter>(); }

    void buildHead() override { character_->setHead("Steel Helmet"); }
    void buildBody() override { character_->setBody("Plate Armor"); }
    void buildWeapon() override { character_->setWeapon("Longsword"); }
    std::unique_ptr<GameCharacter> getResult() override { return std::move(character_); }

private:
    std::unique_ptr<GameCharacter> character_;
};

// 具体建造者:法师
class MageBuilder : public CharacterBuilder {
public:
    MageBuilder() { character_ = std::make_unique<GameCharacter>(); }

    void buildHead() override { character_->setHead("Pointed Hat"); }
    void buildBody() override { character_->setBody("Robe"); }
    void buildWeapon() override { character_->setWeapon("Staff"); }
    std::unique_ptr<GameCharacter> getResult() override { return std::move(character_); }

private:
    std::unique_ptr<GameCharacter> character_;
};

// 指挥者(可选)
class CharacterDirector {
public:
    std::unique_ptr<GameCharacter> createCharacter(CharacterBuilder& builder) {
        builder.buildHead();
        builder.buildBody();
        builder.buildWeapon();
        return builder.getResult();
    }
};

// 客户端代码
int main() {
    KnightBuilder knightBuilder;
    MageBuilder mageBuilder;
    CharacterDirector director;

    auto knight = director.createCharacter(knightBuilder);
    auto mage = director.createCharacter(mageBuilder);

    knight->describe(); // Character: Steel Helmet, Plate Armor, wielding Longsword
    mage->describe();   // Character: Pointed Hat, Robe, wielding Staff

    return 0;
}

代码解析:

  • 将角色构造分解为独立步骤,新增角色类型只需添加新的 ConcreteBuilder
  • 使用 std::unique_ptr 明确所有权转移,防止资源泄漏

3.2 支持链式调用的增强实现

// 流畅接口(Fluent Interface)改进
class AdvancedCharacterBuilder {
public:
    AdvancedCharacterBuilder& withHead(const std::string& head) {
        head_ = head;
        return *this;
    }

    AdvancedCharacterBuilder& withBody(const std::string& body) {
        body_ = body;
        return *this;
    }

    AdvancedCharacterBuilder& withWeapon(const std::string& weapon) {
        weapon_ = weapon;
        return *this;
    }

    std::unique_ptr<GameCharacter> build() {
        auto character = std::make_unique<GameCharacter>();
        character->setHead(head_);
        character->setBody(body_);
        character->setWeapon(weapon_);
        return character;
    }

private:
    std::string head_;
    std::string body_;
    std::string weapon_;
};

// 客户端使用
void createCustomCharacter() {
    auto builder = AdvancedCharacterBuilder();
    auto character = builder.withHead("Hood")
                             .withBody("Leather Armor")
                             .withWeapon("Dagger")
                             .build();
    character->describe();
}

代码解析

  • 通过返回 this 指针实现链式调用,提升代码可读性
  • 支持可选参数和任意顺序设置属性

4. 应用场景示例:HTTP请求构造

class HttpRequest {
public:
    void setMethod(const std::string& method) { method_ = method; }
    void setUrl(const std::string& url) { url_ = url; }
    void addHeader(const std::string& key, const std::string& value) {
        headers_[key] = value;
    }
    void setBody(const std::string& body) { body_ = body; }

    void send() const {
        std::cout << "Sending " << method_ << " " << url_ 
                  << " with body: " << body_ << "\n";
    }

private:
    std::string method_;
    std::string url_;
    std::map<std::string, std::string> headers_;
    std::string body_;
};

class HttpRequestBuilder {
public:
    HttpRequestBuilder() : request_(std::make_unique<HttpRequest>()) {}

    HttpRequestBuilder& method(const std::string& method) {
        request_->setMethod(method);
        return *this;
    }

    HttpRequestBuilder& url(const std::string& url) {
        request_->setUrl(url);
        return *this;
    }

    HttpRequestBuilder& header(const std::string& key, const std::string& value) {
        request_->addHeader(key, value);
        return *this;
    }

    HttpRequestBuilder& body(const std::string& body) {
        request_->setBody(body);
        return *this;
    }

    std::unique_ptr<HttpRequest> build() {
        return std::move(request_);
    }

private:
    std::unique_ptr<HttpRequest> request_;
};

// 使用示例
void sendPostRequest() {
    auto request = HttpRequestBuilder()
        .method("POST")
        .url("https://api.example.com/data")
        .header("Content-Type", "application/json")
        .body(R"({"key": "value"})")
        .build();
    request->send();
}

5. 优缺点分析

优点缺点
分步骤构造复杂对象,代码清晰需定义多个Builder类,增加代码量
支持不同配置和构造顺序对简单对象可能过度设计
隔离复杂构造逻辑与业务代码需维护Builder与Product的同步

6. 调试与优化策略

  • 参数验证:在Builder方法中添加有效性检查,防止非法状态
  • 对象复用:对频繁创建的对象,实现reset()方法重用Builder实例
  • 性能分析:使用std::move优化字符串等大型数据成员的传递效率

模式结构解析网图备份

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2311860.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用GitLink个人建站服务部署Allure在线测试报告

更多技术文章&#xff0c;访问软件测试社区 文章目录 &#x1f680;前言&#x1f511;开通GitLink个人建站服务1. 前提条件2. 登录GitLink平台&#xff08;https://www.gitlink.org.cn/login&#xff09;3. 进入设置>个人建站>我的站点4. 新建站点5. 去仓部进行部署6. 安…

专业学习|多线程、多进程、多协程加速程序运行

学习资料来源&#xff1a;【2021最新版】Python 并发编程实战&#xff0c;用多线程、多进程、多协程加速程序运行_哔哩哔哩_bilibili 若有侵权&#xff0c;联系删除。 一、程序的提速方法——多线程、多进程、多协程 在现代编程中&#xff0c;多线程、多进程和多协程是三种常见…

C/C++蓝桥杯算法真题打卡(Day3)

一、P8598 [蓝桥杯 2013 省 AB] 错误票据 - 洛谷 算法代码&#xff1a; #include<bits/stdc.h> using namespace std;int main() {int N;cin >> N; // 读取数据行数unordered_map<int, int> idCount; // 用于统计每个ID出现的次数vector<int> ids; …

烟花燃放安全管控:智能分析网关V4烟火检测技术保障安全

一、方案背景 在中国诸多传统节日的缤纷画卷中&#xff0c;烟花盛放、烧纸祭祀承载着人们的深厚情感。一方面&#xff0c;烟花璀璨&#xff0c;是对节日欢庆氛围的热烈烘托&#xff0c;寄托着大家对美好生活的向往与期许&#xff1b;另一方面&#xff0c;袅袅青烟、点点烛光&a…

【Bert系列模型】

目录 一、BERT模型介绍 1.1 BERT简介 1.2 BERT的架构 1.2.1 Embedding模块 1.2.2 双向Transformer模块 1.2.3 预微调模块 1.3 BERT的预训练任务 1.3.1 Masked Language Model (MLM) 1.3.2 Next Sentence Prediction (NSP) 1.4 预训练与微调的关系 1.5 小结 二、BERT…

android接入rocketmq

一 前言 RocketMQ 作为一个功能强大的消息队列系统&#xff0c;不仅支持基本的消息发布与订阅&#xff0c;还提供了顺序消息、延时消息、事务消息等高级功能&#xff0c;适应了复杂的分布式系统需求。其高可用性架构、多副本机制、完善的运维管理工具&#xff0c;以及安全控制…

前端数据模拟 Mock.js 学习笔记

mock.js介绍 Mock.js是一款前端开发中拦截Ajax请求再生成随机数据响应的工具&#xff0c;可以用来模拟服务器响应 优点是&#xff1a;非常方便简单&#xff0c;无侵入性&#xff0c;基本覆盖常用的接口数据类型支持生成随机的文本、数字、布尔值、日期、邮箱、链接、图片、颜…

用DeepSeek-R1-Distill-data-110k蒸馏中文数据集 微调Qwen2.5-7B-Instruct!

下载模型与数据 模型下载&#xff1a; huggingface&#xff1a; Qwen/Qwen2.5-7B-Instruct HF MirrorWe’re on a journey to advance and democratize artificial intelligence through open source and open science.https://hf-mirror.com/Qwen/Qwen2.5-7B-Instruct 魔搭&a…

DeepSeek大模型 —— 全维度技术解析

DeepSeek大模型 —— 全维度技术解析 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;可以分享一下给大家。点击跳转到网站。 https://www.captainbed.cn/ccc 文章目录 DeepSeek大模型 —— 全维度技术解析一、模型架构全景解析1…

EasyRTC嵌入式音视频通话SDK:基于ICE与STUN/TURN的实时音视频通信解决方案

在当今数字化时代&#xff0c;实时音视频通信技术已成为人们生活和工作中不可或缺的一部分。无论是家庭中的远程看护、办公场景中的远程协作&#xff0c;还是工业领域的远程巡检和智能设备的互联互通&#xff0c;高效、稳定的通信技术都是实现这些功能的核心。 EasyRTC嵌入式音…

qt open3dAlpha重建

qt open3dAlpha重建 效果展示二、流程三、代码效果展示 二、流程 创建动作,链接到槽函数,并把动作放置菜单栏 参照前文 三、代码 1、槽函数实现 void on_actionAlpha_triggered();//alpha重建 void MainWindow::

《深入浅出数据索引》- 公司内部培训课程笔记

深入浅出数据索引 内容&#xff1a;索引理论&#xff0c;索引常见问题&#xff0c;索引最佳实践&#xff0c;sql优化实战&#xff0c;问答 哈希不支持范围查询 4层 几个亿 5层 几十亿上百亿 B树的分裂&#xff0c;50-50分裂 都是往上插一个元素&#xff08;红黑树是左右旋转&a…

PPT 技能:巧用 “节” 功能,让演示文稿更有序

在制作PPT时&#xff0c;你是否遇到过这样的情况&#xff1a;幻灯片越来越多&#xff0c;内容越来越杂&#xff0c;找某一页内容时翻得眼花缭乱&#xff1f;尤其是在处理大型PPT文件时&#xff0c;如果没有合理的结构&#xff0c;编辑和调整都会变得非常麻烦。这时候&#xff0…

Xss漏洞问题

https://bu1.github.io/2021/01/12/%E7%AC%AC%E5%8D%81%E4%BA%8C%E5%91%A8%EF%BC%9AXSS%E6%BC%8F%E6%B4%9E%E5%AD%A6%E4%B9%A0%E5%AE%9E%E6%88%98/ 后端绕开了前端&#xff0c;直接调用接口入库&#xff1a; <select οnchange“alert(1)”>12 前端拿到这个文本后&…

Docker概念与架构

文章目录 概念docker与虚拟机的差异docker的作用docker容器虚拟化 与 传统虚拟机比较 Docker 架构 概念 Docker 是一个开源的应用容器引擎。诞生于 2013 年初&#xff0c;基于 Go 语言实现。Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#xf…

3.使用ElementUI搭建侧边栏及顶部栏

1. 安装ElementUI ElementUI是基于 Vue 2.0 的桌面端组件库。使用之前&#xff0c;需要在项目文件夹中安装ElementUI&#xff0c;在终端中输入以下命令&#xff0c;进行安装。 npm i element-ui -S并在main.js中引入ElementUI 2. 使用elmentUI组件进行页面布局 2.1 清空原…

C# OPC DA获取DCS数据(提前配置DCOM)

OPC DA配置操作手册 配置完成后&#xff0c;访问远程ip&#xff0c;就能获取到服务 C#使用Interop.OPCAutomation采集OPC DA数据&#xff0c;支持订阅&#xff08;数据变化&#xff09;、单个读取、单个写入、断线重连

不同开发语言之for循环的用法、区别总结

一、Objective-C &#xff08;1&#xff09;标准的c风格 for (int i 0; i < 5; i) {NSLog("i %d", i); } &#xff08;2&#xff09;for in循环。 NSArray *array ["apple", "banana", "orange"]; for (NSString *fruit in …

MuBlE:为机器人操作任务规划提供了逼真的视觉观察和精确的物理建模

2025-03-05&#xff0c;由华为诺亚方舟实验室、捷克技术大学和帝国理工学院联合开发的MuBlE&#xff08;MuJoCo and Blender simulation Environment&#xff09;模拟环境和基准测试。通过结合MuJoCo物理引擎和Blender高质量渲染&#xff0c;为机器人操作任务规划提供了逼真的视…

ASP.NET Core 6 MVC 文件上传

概述 应用程序中的文件上传是一项功能&#xff0c;用户可以使用该功能将用户本地系统或网络上的文件上传到 Web 应用程序。Web 应用程序将处理该文件&#xff0c;然后根据需要对文件进行一些验证&#xff0c;最后根据要求将该文件存储在系统中配置的用于保存文件的存储中&#…