当前位置: 首页 > 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;这次先写一下未成功的…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...

用机器学习破解新能源领域的“弃风”难题

音乐发烧友深有体会&#xff0c;玩音乐的本质就是玩电网。火电声音偏暖&#xff0c;水电偏冷&#xff0c;风电偏空旷。至于太阳能发的电&#xff0c;则略显朦胧和单薄。 不知你是否有感觉&#xff0c;近两年家里的音响声音越来越冷&#xff0c;听起来越来越单薄&#xff1f; —…...

C#学习第29天:表达式树(Expression Trees)

目录 什么是表达式树&#xff1f; 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持&#xff1a; 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...

nnUNet V2修改网络——暴力替换网络为UNet++

更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...

comfyui 工作流中 图生视频 如何增加视频的长度到5秒

comfyUI 工作流怎么可以生成更长的视频。除了硬件显存要求之外还有别的方法吗&#xff1f; 在ComfyUI中实现图生视频并延长到5秒&#xff0c;需要结合多个扩展和技巧。以下是完整解决方案&#xff1a; 核心工作流配置&#xff08;24fps下5秒120帧&#xff09; #mermaid-svg-yP…...