当前位置: 首页 > news >正文

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

注意:复现代码时,确保 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 Longswordmage->describe();   // Character: Pointed Hat, Robe, wielding Staffreturn 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优化字符串等大型数据成员的传递效率

模式结构解析网图备份

在这里插入图片描述

相关文章:

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

注意&#xff1a;复现代码时&#xff0c;确保 VS2022 使用 C17/20 标准以支持现代特性。 分步骤构造复杂对象&#xff0c;实现灵活装配 1. 模式定义与用途 核心目标&#xff1a;将复杂对象的构建过程分离&#xff0c;使得同样的构建步骤可以创建不同的表示形式。 常见场景&am…...

【杂谈】信创电脑华为w515(统信系统)登录锁定及忘记密码处理

华为w515麒麟芯片版&#xff0c;还有非麒麟芯片版本&#xff0c;是一款信创电脑&#xff0c;一般安装的UOS系统。 准备一个空U盘&#xff0c;先下载镜像文件及启动盘制作工具&#xff0c;连接如下&#xff1a; 百度网盘 请输入提取码 http://livecd.uostools.com/img/apps/l…...

VBA信息获取与处理第五节:如何在单个工作表中查找某个给定值

《VBA信息获取与处理》教程(版权10178984)是我推出第六套教程&#xff0c;目前已经是第一版修订了。这套教程定位于最高级&#xff0c;是学完初级&#xff0c;中级后的教程。这部教程给大家讲解的内容有&#xff1a;跨应用程序信息获得、随机信息的利用、电子邮件的发送、VBA互…...

版本控制器Git和gdb

一.版本控制器Git 1.版本控制简单来讲可以对每一份代码版本进行复制保存&#xff0c;保证每一版代码都可查 2.仓库的本质也是一个文件夹 3.git既是一个客户端&#xff0c;也是一个服务器&#xff0c;是一个版本控制器。而gitee和GitHub都是基于git的网站或平台 4.git的基本…...

关于tresos Studio(EB)的MCAL配置之GPT

概念 GPT&#xff0c;全称General Purpose Timer&#xff0c;就是个通用定时器&#xff0c;取的名字奇怪了点。定时器是一定要的&#xff0c;要么提供给BSW去使用&#xff0c;要么提供给OS去使用。 配置 General GptDeinitApi控制接口Gpt_DeInit是否启用 GptEnableDisable…...

大学至今的反思与总结

现在是2025年的3月5日&#xff0c;我大三下学期。 自大学伊始&#xff0c;我便以考研作为自己的目标&#xff0c;有时还会做自己考研上岸头部985,211&#xff0c;offer如潮水般涌来的美梦。 但是我却忽略了一点&#xff0c;即便我早早下定了决心去考研&#xff0c;但并没有早…...

我们来学nginx -- 优化下游响应速度

优化下游响应速度 题记启用 Gzip 压缩优化缓冲区设置设置超时时间 题记 专家给出的配置文件真是…&#xff0c;信息量有点大啊&#xff01; nginx&#xff1a;我只想作为一个简单的代理专家爸爸&#xff1a;都是为了你好&#xff01; 这样&#xff0c;先从有关响应速度的角度&…...

国内外优秀AI外呼产品推荐

在数字化转型浪潮中&#xff0c;AI外呼系统凭借其高效率、低成本、精准交互的特点&#xff0c;成为企业客户触达与服务的核心工具。本文基于行业实践与技术测评&#xff0c;推荐国内外表现突出的AI外呼产品&#xff0c;重点解析国内标杆企业云蝠智能&#xff0c;并对比其他代表…...

观察者模式的C++实现示例

核心思想 观察者模式是一种行为型设计模式&#xff0c;定义了对象之间的一对多依赖关系。当一个对象&#xff08;称为Subject&#xff0c;主题&#xff09;的状态发生改变时&#xff0c;所有依赖于它的对象&#xff08;称为Observer&#xff0c;观察者&#xff09;都会自动收到…...

爬虫(持续更新ing)

爬虫&#xff08;持续更新ing&#xff09; # 网络请求 # url统一资源定位符&#xff08;如&#xff1a;https://www.baidu.com&#xff09; # 请求过程&#xff1a;客户端的web浏览器向服务器发起请求 # 请求又分为四部分&#xff1a;请求网址&#xff0c;请求方法&#xff08…...

AD学习-最小系统板,双层

第一章 简单电阻容模型的创建 捕捉栅格在摆放器件时&#xff0c;一般设置成 10mil。移动器件时一般设置成100mil。 比如绘制电容的原理图库&#xff0c;直接就是两根线条竖着成电容&#xff0c; 按Tab键进行颜色变更&#xff0c;按shift键拖动会复制一个出来。 …...

自动驾驶---不依赖地图的大模型轨迹预测

1 前言 早期传统自动驾驶方案通常依赖高精地图&#xff08;HD Map&#xff09;提供道路结构、车道线、交通规则等信息&#xff0c;可参考博客《自动驾驶---方案从有图迈进无图》&#xff0c;本质上还是存在问题&#xff1a; 数据依赖性高&#xff1a;地图构建成本昂贵&#xf…...

【五.LangChain技术与应用】【8.LangChain提示词模板基础:从入门到精通】

早上八点,你端着咖啡打开IDE,老板刚甩来需求:“做个能自动生成产品描述的AI工具”。你自信满满地打开ChatGPT的API文档,结果半小时后对着满屏的"输出结果不稳定"、"格式总出错"抓耳挠腮——这时候你真需要好好认识下LangChain里的提示词模板了。 一、…...

【AGI】智谱开源2025:一场AI技术民主化的革命正在到来

智谱开源2025&#xff1a;一场AI技术民主化的革命正在到来 引言&#xff1a;开源&#xff0c;一场技术平权的革命一、CogView4&#xff1a;中文AI生成的里程碑1. 破解汉字生成的“AI魔咒”2. 开源协议与生态赋能 二、AutoGLM&#xff1a;人机交互的范式跃迁1. 自然语言驱动的跨…...

Markdown HTML 图像语法

插入图片 Markdown ![图片描述](图片链接)一般来说&#xff0c;直接复制粘贴过来就行了&#xff0c;部分网页/应用可以拖拽&#xff0c;没人会真敲图片的链接吧…… 示例图片&#xff1a; ![Creeper?](https://i-blog.csdnimg.cn/direct/f5031c8c4f15421c9882d7eb23540b8…...

DeepSeek 角色设定与风格控制

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…...

国产化替换案例:CACTER邮件网关为Groupwise系统加固邮件安全防线

电子邮件作为企业信息流转的命脉&#xff0c;承载着商业机密与客户数据。然而&#xff0c;网络攻击手段日益复杂&#xff0c;钓鱼邮件等威胁正快速侵蚀企业安全防线。据《2024年第四季度企业邮箱安全性研究报告》显示&#xff0c;2024年Q4企业邮箱用户遭遇的钓鱼邮件数量激增至…...

Element UI-Select选择器结合树形控件终极版

Element UI Select选择器控件结合树形控件实现单选和多选&#xff0c;并且通过v-model的方式实现节点的双向绑定&#xff0c;封装成vue组件&#xff0c;文件名为electricity-meter-tree.vue&#xff0c;其代码如下&#xff1a; <template><div><el-select:valu…...

《底层逻辑》总结书摘

《底层逻辑》由张羽所著&#xff0c;聚焦于职场与个人发展&#xff0c;深入阐述了定位、结果、学习等十大底层逻辑&#xff0c;旨在帮助读者掌握思考和解决问题的有效方法&#xff0c;提升职场竞争力与个人成就。 核心观点&#xff1a;思维和行动决定命运&#xff0c;格局与价值…...

【Linux】【网络】UDP打洞-->不同子网下的客户端和服务器通信(未成功版)

【Linux】【网络】UDP打洞–>不同子网下的客户端和服务器通信&#xff08;未成功版&#xff09; 上次说基于UDP的打洞程序改了五版一直没有成功&#xff0c;要写一下问题所在&#xff0c;但是我后续又查询了一些资料&#xff0c;成功实现了&#xff0c;这次先写一下未成功的…...

RestClient

什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端&#xff0c;它允许HTTP与Elasticsearch 集群通信&#xff0c;而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级&#xff…...

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试&#xff0c;通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小&#xff0c;增大可提高计算复杂度duration: 测试持续时间&#xff08;秒&…...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中&#xff0c;将 long long 类型转换为 QString 可以通过以下两种常用方法实现&#xff1a; 方法 1&#xff1a;使用 QString::number() 直接调用 QString 的静态方法 number()&#xff0c;将数值转换为字符串&#xff1a; long long value 1234567890123456789LL; …...