【第四节】C++设计模式(创建型模式)-Builder(建造者)模式
目录
引言
一、Builder 模式概述
二、Builder 模式举例
三、Builder 模式的结构
四、Builder 模式的实现
五、Builder 模式的优缺点
六、总结
引言
Builder 模式是一种创建型设计模式,旨在将复杂对象的构建过程与其表示分离。通过一步步构建对象,Builder 模式允许在构建过程中引入参数,从而生成不同的对象表示。本文将通过理论讲解和代码示例,深入探讨 Builder 模式的核心思想、适用场景及其实现方式。
一、Builder 模式概述
核心思想
Builder 模式的核心思想是将复杂对象的构建过程分解为多个步骤,并通过一个指导者(Director)对象来协调这些步骤。这样做的好处是:
构建过程与表示分离:对象的构建过程独立于其最终表示,使得相同的构建过程可以生成不同的对象。
灵活性:通过在每一步骤中引入参数,可以灵活地调整对象的构建过程。
适用场景
Builder 模式适用于以下场景:
需要创建的对象非常复杂,由多个部分组成。
对象的构建过程需要分步骤进行,且每个步骤可能需要不同的参数。
希望将对象的构建过程与其表示分离,以便生成不同的对象表示。
二、Builder 模式举例
建造一栋房屋是一个复杂的过程,通常分为多个步骤,例如:
(1)打地基:为房屋奠定基础。
(2)搭建框架:构建房屋的主体结构。
(3)安装水电:布置水管、电线等基础设施。
(4)装修:进行内部和外部的装饰。
每个步骤都需要不同的材料和工艺,且可以根据需求进行调整。例如,地基的深度、框架的材料、装修的风格等都可以根据房屋的用途和预算进行定制。
在房屋建造过程中,Builder 模式可以很好地发挥作用:
分步骤构建:将房屋的建造过程分解为多个步骤(如打地基、搭建框架等),每个步骤由专门的工人或团队负责。
参数化构建:在每个步骤中引入不同的参数(如材料选择、设计风格等),从而生成不同的房屋。
统一管理:通过一个总指挥(Director)来协调各个步骤,确保房屋的建造过程有序进行。
通过 Builder 模式,相同的建造过程可以生成不同的房屋。例如:
经济型房屋:使用低成本材料,简化装修。
豪华型房屋:使用高端材料,精心设计装修。
环保型房屋:采用绿色建材,注重节能设计。
Builder 模式解决的问题与此类似:当我们需要创建的对象非常复杂时,可以通过分步骤构建对象,并在每一步骤中引入参数,从而生成不同的对象表示。
三、Builder 模式的结构
典型结构图

Builder 模式的典型结构包括以下几个角色:
Product(产品):最终要构建的复杂对象。
Builder(构建者):定义构建对象的各个步骤的接口。
ConcreteBuilder(具体构建者):实现 Builder 接口,完成对象的具体构建。
Director(指导者):负责调用 Builder 的步骤,控制对象的构建过程。
关键点
分步骤构建:Builder 模式通过分步骤构建对象,使得构建过程更加清晰和可控。
参数化构建:在每一步骤中引入参数,可以生成不同的对象表示。
四、Builder 模式的实现
代码示例
以下是一个简单的 Builder 模式实现示例,展示了如何分步骤构建一个复杂对象。
产品类定义
// Product.h
#ifndef _PRODUCT_H_
#define _PRODUCT_H_class Product {
public:Product();~Product();void ProducePart();
protected:
private:
};class ProductPart {
public:ProductPart();~ProductPart();ProductPart* BuildPart();
protected:
private:
};#endif // ~_PRODUCT_H_
构建者类定义
// Builder.h
#ifndef _BUILDER_H_
#define _BUILDER_H_
#include <string>
using namespace std;class Product;class Builder {
public:virtual ~Builder();virtual void BuildPartA(const string& buildPara) = 0;virtual void BuildPartB(const string& buildPara) = 0;virtual void BuildPartC(const string& buildPara) = 0;virtual Product* GetProduct() = 0;
protected:Builder();
private:
};class ConcreteBuilder : public Builder {
public:ConcreteBuilder();~ConcreteBuilder();void BuildPartA(const string& buildPara);void BuildPartB(const string& buildPara);void BuildPartC(const string& buildPara);Product* GetProduct();
protected:
private:
};#endif // ~_BUILDER_H_
构建者类实现
// Builder.cpp
#include "Builder.h"
#include "Product.h"
#include <iostream>
using namespace std;Builder::Builder() {}
Builder::~Builder() {}ConcreteBuilder::ConcreteBuilder() {}
ConcreteBuilder::~ConcreteBuilder() {}void ConcreteBuilder::BuildPartA(const string& buildPara) {cout << "Step1: Build PartA..." << buildPara << endl;
}void ConcreteBuilder::BuildPartB(const string& buildPara) {cout << "Step2: Build PartB..." << buildPara << endl;
}void ConcreteBuilder::BuildPartC(const string& buildPara) {cout << "Step3: Build PartC..." << buildPara << endl;
}Product* ConcreteBuilder::GetProduct() {BuildPartA("pre-defined");BuildPartB("pre-defined");BuildPartC("pre-defined");return new Product();
}
指导者类定义
// Director.h
#ifndef _DIRECTOR_H_
#define _DIRECTOR_H_class Builder;class Director {
public:Director(Builder* bld);~Director();void Construct();
protected:
private:Builder* _bld;
};#endif // ~_DIRECTOR_H_
指导者类实现
// Director.cpp
#include "Director.h"
#include "Builder.h"Director::Director(Builder* bld) {_bld = bld;
}Director::~Director() {}void Director::Construct() {_bld->BuildPartA("user-defined");_bld->BuildPartB("user-defined");_bld->BuildPartC("user-defined");
}
测试程序
// main.cpp
#include "Builder.h"
#include "Product.h"
#include "Director.h"
#include <iostream>
using namespace std;int main(int argc, char* argv[]) {Director* d = new Director(new ConcreteBuilder());d->Construct();return 0;
}
五、Builder 模式的优缺点
优点
构建过程与表示分离:对象的构建过程独立于其最终表示,使得相同的构建过程可以生成不同的对象。
灵活性:通过在每一步骤中引入参数,可以灵活地调整对象的构建过程。
易于扩展:新增构建步骤或调整构建顺序非常方便。
缺点
复杂性增加:随着构建步骤的增多,Builder 模式的实现可能变得复杂。
代码冗余:每个具体构建者类都需要实现相同的构建步骤接口,可能导致代码冗余。
六、总结
Builder 模式是一种强大的设计模式,适用于复杂对象的构建。它通过分步骤构建对象,并将构建过程与表示分离,提供了灵活性和可扩展性。然而,在面对简单对象的构建时,Builder 模式可能显得过于复杂。因此,在实际开发中,应根据具体需求选择合适的设计模式。
相关文章:
【第四节】C++设计模式(创建型模式)-Builder(建造者)模式
目录 引言 一、Builder 模式概述 二、Builder 模式举例 三、Builder 模式的结构 四、Builder 模式的实现 五、Builder 模式的优缺点 六、总结 引言 Builder 模式是一种创建型设计模式,旨在将复杂对象的构建过程与其表示分离。通过一步步构建对象,…...
排查JVM的一些命令
查看JVM相关信息的方法 环境: Win10, jdk17 查看端口的Pid netstat -ano | findstr <端口号>列出当前运行的JVM进程 ## 用于输出JVM中运行的进程状态信息。通过jps,可以快速获取Java进程的PID(进程标识符), …...
uni-app(位置1)
文章目录 一、获取当前的地理位置、速度 uni.getLocation(OBJECT)二、打开地图选择位置 uni.chooseLocation(OBJECT)三、使用应用内置地图查看位置。uni.openLocation(OBJECT) 一、获取当前的地理位置、速度 uni.getLocation(OBJECT) App平台 manifest中配置好自己的地图厂商k…...
某手sig3-ios算法 Chomper黑盒调用
Chomper-iOS界的Unidbg 最近在学习中发现一个Chomper框架,Chomper 是一个模拟执行iOS可执行文件的框架,类似于安卓端大名鼎鼎的Unidbg。 这篇文章使用Chomper模拟执行某手的sig3算法,初步熟悉该框架。这里只熟悉模拟执行步骤以及一些常见的…...
登录-05.JWT令牌-介绍
一.JWT令牌 JWT令牌是一种简洁的、自包含的格式,用于在通讯双方之间以json数据格式安全的传输数据。说白了,JWT令牌就是将json格式的数据进行封装,从而实现安全传输。 所谓简洁,就是指JWT令牌就是一个简单的字符串。 所谓自包含…...
Mac下Python版本管理,适用于pyenv不起作用的情况
前言 声明:之前也在网上看到过可以使用pyenv来管理python版本,但由于作者的python安装路径实在是繁杂不堪,因此安装完成pyenv体验下来没有任何用处,但偶然发现vscode似乎可以看到各个python版本,因此写下这篇博客记录…...
Ubuntu 服务器Llama Factory 搭建DeepSeek-R1微调训练环境
1.首先了解一下什么是LLM微调 LLM 微调指的是在已经预训练好的大型语言模型基础上,使用特定的任务数据或领域数据,通过进一步的训练来调整模型的参数,使其在特定任务或领域上能够表现得更好。简单来说,就是对一个已经具备了丰富语…...
【redis】redis内存管理,过期策略与淘汰策略
一:Redis 的过期删除策略及处理流程如下: 1. 过期删除策略 Redis 通过以下两种策略删除过期键: 1.1 惰性删除 触发时机:当客户端访问某个键时,Redis 会检查该键是否过期。执行流程: 客户端请求访问键。…...
RabbitMQ学习—day6—死信队列与延迟队列
目录 死信队列 1. 死信的概念 2. 死信的来源 实战演练 1. 消息TTL过期 2. 队列达到最大长度 3. 消息被拒绝 延迟队列 概念 使用场景 TTL的两种设置 死信队列 1. 死信的概念 1.1 先从概念解释上搞清楚这个定义,死信,顾名思义就是无法被消费的…...
seacmsv9联合注入数据以及绕过 ORDERBY
seacmsv9联合注入数据 php源码 <?php session_start(); require_once("../../include/common.php"); $id (isset($gid) && is_numeric($gid)) ? $gid : 0; $page (isset($page) && is_numeric($page)) ? $page : 1; $type (isset($type) …...
day58 第十一章:图论part08
拓扑排序精讲 关键: 先找到入度为0的节点,把这些节点加入队列/结果,然后依次循环再找。 #include <iostream> #include <vector> #include <queue> #include <unordered_map> using namespace std; int main() {int …...
网络安全-openssl工具
OpenSSl是一个开源项目,包括密码库和SSL/TLS工具集。它已是在安全领域的事实标准,并且拥有比较长的历史,现在几乎所有的服务器软件和很多客户端都在使用openssl,其中基于命令行的工具是进行加密、证书管理以及测试最常用到的软件。…...
Java面试第六山!《MySQL基础知识点》
一、引言 MySQL 作为一款广泛使用的开源关系型数据库管理系统,在软件开发领域占据着重要地位。无论是小型项目还是大型企业级应用,都能看到 MySQL 的身影。今天就来和大家分享 MySQL 的相关知识,帮助大家更好地应对日常开发和面试。 二、My…...
云计算中的API网关是什么?为什么它很重要?
在云计算架构中,API网关(API Gateway)是一个重要的组件,主要用于管理、保护和优化不同服务之间的接口(API)通信。简单来说,API网关就像是一个中介,它充当客户端和后端服务之间的“桥…...
【WebGL】fbo双pass案例
双pass渲染案例(离线渲染一个三角面,然后渲染到一个占满屏幕的矩阵上) 离线渲染如何需要开启深度测试的话,需要额外操作,这里不展开 <!DOCTYPE html> <html lang"en"><head><meta ch…...
Unity面板介绍_层级面板(23.1.1)
一、Inspector(检视面板) 显示当前选定游戏对象附加的组件及其属性信息。为重要游戏物体选择图标 二、面板详情...
详解Nginx 配置
一、Nginx 介绍 Nginx 是一款轻量级的 Web 服务器 / 反向代理服务器及电子邮件(IMAP/POP3)代理服务器。它由俄罗斯的程序设计师 Igor Sysoev 所开发,自 2004 年发布以来,凭借其高性能、低内存消耗、高并发处理能力等特点…...
数据库系统概念
1. 绪论 数据库的基本概念: 数据(data): 数据库中存储的基本对象, 可以是文字, 声音, 图片, 视频等。 数据库(DB): 概括来说就是永久存储, 有组织, 可共享的大量数据的集合。 数据库管理系统(DBMS): 和操作系统一样是计算机基础软件, 主要有数据定义语言(DDL, 对数据对象的组…...
51单片机学习之旅——定时器
打开软件 1与其它等于其它,0与其它等于0 1或其它等于1,0或其它等于其它 TMODTMOD&0xF0;//0xF01111 0000进行与操作,高四位保持,低四位清零,高四位定时器1,低四位定时器0 TMODTMOD|0x01;//0x010000 0…...
一台服务器将docker image打包去另一天服务器安装这个镜像
一台服务器将docker image打到去另一天服务器安装这个镜像 1. 打包2.另一台服务器执行 1. 打包 docker save -o nebula-graph-studio.tar harbor1.vm.example.lan/dockerio/vesoft/nebula-graph-studioxxx.tar 是打包好的文件 后面的是 docker image 2.另一台服务器执行 docke…...
别再只盯着效率了!聊聊DCDC电源在轻载时,PSM、Burst、FCM三种模式到底该怎么选?
DCDC电源轻载模式深度解析:PSM、Burst、FCM的工程实践指南 在IoT设备和便携式电子产品的设计中,电源管理芯片的轻载性能往往成为决定产品续航能力的关键因素。某次深夜调试中,当我用示波器捕捉到一颗纽扣电池供电的传感器模组在待机时产生的异…...
python devspace
# 聊聊Python DevSpace:一个让开发环境更清爽的工具 最近在项目里折腾环境配置,又遇到了老问题。不同的项目依赖不同的Python版本,不同的库版本,有时候甚至需要不同的系统环境。虚拟环境能解决一部分问题,但涉及到系统…...
企业云盘ROI计算:让你的老板心服口服
开篇一个真实故事: 某设计院信息科主任老张,连续三年向院长申请企业云盘采购预算,前两次都被驳回,理由是"看不出回报"。第三年,他带了一份12页的ROI分析报告,院长当场批准,预算比申请…...
告别截图!用mutool draw命令把PDF批量转成高清PNG图片(附Python脚本)
高效PDF转PNG全攻略:用mutool实现批量自动化处理 每次需要从PDF中提取页面制作演示文稿或分享内容时,手动截图不仅效率低下,画质也难以保证。作为经常处理技术文档的内容创作者,我发现mutool这个命令行工具能完美解决这个问题——…...
mysql如何快速判断两个数据库结构差异_使用mysqldiff工具.txt
动画系统必须用模板参数控制类型,支持Animation<vec4>和Animation<quat>共享插值逻辑与生命周期管理,要求类型提供static lerp或特化基础路径,播放状态与采样解耦,关键帧用连续内存存储,组合靠BlendAnimat…...
别再只改YAML了!手把手教你从零实现YOLOv8的MSAM注意力模块(附完整代码)
从零构建YOLOv8的MSAM注意力模块:多尺度特征融合实战指南 在目标检测领域,YOLOv8凭借其出色的速度和精度平衡成为工业界的热门选择。但当你面对复杂场景中的多尺度目标时,是否发现模型对小物体或遮挡目标的检测效果不尽如人意?传统…...
使用Jmeter对接口进行压力测试
今天第一次使用Jmeter对系统进行了压力测试,测试了一下纯数据库方案以及添加了缓存的方案,结果惊人。只使用MySQL处理请求在设置并发量为每秒1000次的时候,可以看到MySQL的处理速度已经很慢了,平均响应时间达到了5235ms使用Caffei…...
远程健康监测的终极解决方案:rPPG开源项目完整指南
远程健康监测的终极解决方案:rPPG开源项目完整指南 【免费下载链接】rppg Benchmark Framework for fair evaluation of rPPG 项目地址: https://gitcode.com/gh_mirrors/rpp/rppg 你是否想过,仅仅通过普通摄像头就能监测心率和血压?&…...
别再手动lock/unlock了!Qt多线程开发中QMutexLocker的正确打开方式(附源码对比)
Qt多线程开发:用QMutexLocker实现零失误的锁管理 在Qt多线程开发中,资源竞争问题就像房间里的大象——谁都无法忽视。传统QMutex的手动lock/unlock操作看似简单,却隐藏着巨大的隐患。想象一下,在一个复杂的业务逻辑中,…...
人形机器人半马:进步与失控并存,短板暴露促进行业迭代
北京亦庄:机器人半马现意外在北京亦庄南海子公园的终点线前,“天工Ultra”曾是去年北京亦庄人形机器人半程马拉松的王者,以2小时40分42秒的成绩夺冠。但在今年的比赛中,它触线后未停下,径直冲入路边绿化带,…...
