9.建造者模式 (Builder Pattern)
定义
建造者模式(Builder Pattern)是一种创建型设计模式,旨在将复杂对象的构建过程与它的表示分离,使得同样的构建过程可以创建不同的表示。该模式的核心思想是通过一步步地构建一个复杂的对象,每个步骤独立且可扩展,并且最终的产品(对象)可以通过不同的构建步骤得到不同的结果。
结构:
建造者模式通常由以下几个角色组成:
Product(产品):最终构建出来的复杂对象。
Builder(建造者):抽象建造者,定义了构建各个部件的接口,通常会有一个返回产品的方法。
ConcreteBuilder(具体建造者):实现了 Builder 接口,负责构建具体的部件,并最终生成产品。
Director(指挥者):负责指导建造者进行构建,按照一定的顺序来调用建造者的方法,最终获取产品。
Client(客户端):使用 Director 和 Builder 来构建产品。
类的设计分析:
1. House(产品类)
class House {// 复杂对象的定义,包含房屋的不同部分
};House 类表示最终要构建的复杂对象。
在这个例子中,它代表一个房子,包含房子的多个部分,如墙壁、屋顶、地板等。
2. HouseBuilder(抽象建造者)
class HouseBuilder {
public:House* GetResult() {return pHouse;}virtual ~HouseBuilder() {}
protected:House* pHouse;virtual void BuildPart1() = 0;virtual void BuildPart2() = 0;virtual void BuildPart3() = 0;virtual void BuildPart4() = 0;virtual void BuildPart5() = 0;
};
- HouseBuilder 类 是一个抽象建造者,它定义了建造过程中的各个步骤,如 BuildPart1 到 BuildPart5 方法。这些方法是用来构建房子的不同部分的。
- GetResult() 方法返回最终构建的产品(House 对象)。
- HouseBuilder 中的具体部分构建由继承类实现。
3. StoneHouse(具体产品类)
class StoneHouse : public House {// 石头房子可能有一些特定的功能
};
4. StoneHouseBuilder(具体建造者)
class StoneHouseBuilder : public HouseBuilder {
protected:virtual void BuildPart1() {// 构建房子的第一个部分(例如,地基)}virtual void BuildPart2() {// 构建房子的第二个部分(例如,墙壁)}virtual void BuildPart3() {// 构建房子的第三个部分(例如,屋顶)}virtual void BuildPart4() {// 构建房子的第四个部分(例如,窗户)}virtual void BuildPart5() {// 构建房子的第五个部分(例如,门)}
};
- StoneHouseBuilder 类 是 HouseBuilder 的具体实现类,负责实现如何一步步构建 StoneHouse(石头房子)的各个部分。每个 BuildPart 方法的实现可能会根据不同的房屋类型进行不同的构建。
5. HouseDirector(指挥者)
class HouseDirector {
public:HouseBuilder* pHouseBuilder;HouseDirector(HouseBuilder* pHouseBuilder) {this->pHouseBuilder = pHouseBuilder;}House* Construct() {pHouseBuilder->BuildPart1();for (int i = 0; i < 4; i++) {pHouseBuilder->BuildPart2();}bool flag = pHouseBuilder->BuildPart3();if (flag) {pHouseBuilder->BuildPart4();}pHouseBuilder->BuildPart5();return pHouseBuilder->GetResult();}
};
- HouseDirector 类 是指挥者角色,负责使用建造者 HouseBuilder 来构建产品(房子)。它定义了房子的建造过程,按照一定顺序调用建造者的各个方法,最终返回建造好的 House 产品。
6. Client(客户端)
- 客户端负责创建具体的建造者(如 StoneHouseBuilder)和指挥者(HouseDirector),并通过指挥者来完成房子的建造。
实现步骤
1.定义产品:首先定义 House 类,它包含房子各个部分的数据结构。
2.创建抽象建造者:定义一个 HouseBuilder 类,包含构建各个部分的抽象方法,以及返回最终产品的方法 GetResult。
3.创建具体建造者:实现 HouseBuilder 类的具体子类(如 StoneHouseBuilder),提供每个构建步骤的具体实现。
4.创建指挥者:定义一个 HouseDirector 类,它使用具体建造者按照顺序来构建房子。
5.客户端调用:客户端可以创建具体的建造者和指挥者,并通过指挥者来构建房子。
调用示例:
int main() {// 创建具体的建造者StoneHouseBuilder* builder = new StoneHouseBuilder();// 创建指挥者并传入建造者HouseDirector* director = new HouseDirector(builder);// 开始构建房子House* house = director->Construct();// 输出构建的结果std::cout << "House is built!" << std::endl;delete builder;delete director;delete house;return 0;
}
什么场景使用 Builder Pattern
建造者模式适用于以下几种场景:
复杂对象的创建过程:当一个对象的构建过程非常复杂时(有多个部件或多个构建步骤),可以使用建造者模式将构建过程拆分成多个步骤,使得每个步骤独立,并且支持不同的构建方式。
例如,构建复杂的文件解析器、数据库连接器、UI 界面等。
对象的组成部分不变,但表现形式不同:当构建的对象(如房子)由多个部件组成,但可以有不同的表现形式时,可以使用建造者模式。
例如,构建不同类型的房子(如木房子、石房子等),它们共享相同的构建步骤,但具体实现会有所不同。
需要一步一步构建对象的情况:当构建一个对象需要分多个步骤,且顺序不可随意改变时,建造者模式特别适用。
避免对象构建过程的重复:如果有多个地方需要重复相同的对象构建逻辑,建造者模式可以将构建过程封装在 Builder 类中,避免代码重复。
总结
建造者模式通过分离复杂对象的构建过程和对象的表示,使得构建过程更加灵活,支持多种对象表示方式。在实际开发中,当对象的构建过程繁琐且有多个可选的组成部分时,建造者模式是一种非常有效的设计模式。
相关文章:
9.建造者模式 (Builder Pattern)
定义 建造者模式(Builder Pattern)是一种创建型设计模式,旨在将复杂对象的构建过程与它的表示分离,使得同样的构建过程可以创建不同的表示。该模式的核心思想是通过一步步地构建一个复杂的对象,每个步骤独立且可扩展&…...

OpenCV:特征检测总结
目录 一、什么是特征检测? 二、OpenCV 中的常见特征检测方法 1. Harris 角点检测 2. Shi-Tomasi 角点检测 3. Canny 边缘检测 4. SIFT(尺度不变特征变换) 5. ORB 三、特征检测的应用场景 1. 图像匹配 2. 运动检测 3. 自动驾驶 4.…...

Clion开发STM32时使用stlink下载程序与Debug调试
一、下载程序 先创建一个文件夹: 命名:stlink.cfg 写入以下代码: # choose st-link/j-link/dap-link etc. #adapter driver cmsis-dap #transport select swdsource [find interface/stlink.cfg]transport select hla_swdsource [find target/stm32f4x.…...

电脑开机键一闪一闪打不开
家人们谁懂啊!本来打算愉快地开启游戏时光,或者高效处理工作任务,结果按下电脑开机键后,它就只是一闪一闪的,怎么都打不开。相信不少朋友都遭遇过这种令人崩溃的场景,满心的期待瞬间化为焦急与无奈。电脑在…...

深度学习 Pytorch 基础网络手动搭建与快速实现
为了方便后续练习的展开,我们尝试自己创建一个数据生成器,用于自主生成一些符合某些条件、具备某些特性的数据集。 导入相关的包 # 随机模块 import random# 绘图模块 import matplotlib as mpl import matplotlib.pyplot as plt# 导入numpy import nu…...

Sqli-labs靶场实录(一):Basic Challenges
sqli-labs靶场实录:Basic Challenges sql手注基本流程Less-11.1探测注入点1.2判断字段数1.3判断回显位1.4提取数据库基本信息1.5拖取敏感数据 Less-2Less-3Less-4Less5爆表爆列名 Less6爆库爆表爆列名 Less7猜解数据库长度逐字符爆破数据库名 Less8爆库 Less9爆库 Less10Less11…...

2024最新版Node.js详细安装教程(含npm配置淘宝最新镜像地址)
一:Node.js安装 浏览器中搜索Nodejs,或直接用网址:Node.js — 在任何地方运行 JavaScript 建议此处下载长期支持版本(红框内): 开始下载,完成后打开文件: 进入安装界面,在此处勾选,再点击n…...

RK3568使用QT搭建TCP服务器和客户端
文章目录 一、让RK3568开发板先连接上wifi二、客户端代码1. `widget.h` 文件2. `widget.cpp` 文件**详细讲解**1. **`Widget` 类构造函数 (`Widget::Widget`)**2. **UI 布局 (`setupUI`)**3. **连接按钮的槽函数 (`onConnectClicked`)**4. **发送消息按钮的槽函数 (`onSendMess…...

Android学习20 -- 手搓App2(Gradle)
1 前言 昨天写了一个完全手搓的:Android学习19 -- 手搓App-CSDN博客 后面谷歌说不要用aapt,d8这些来搞。其实不想弄Gradle的,不过想着既然开始了,就多看一些。之前写过一篇Gradle,不过是最简单的编译,不涉…...

LeetCode - Google 大模型10题 第2天 Position Embedding(位置编码) 3题
欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/145454489 在 Transformer 架构中,位置编码(Position Embedding) 是辅助模型理解序列中元素顺序的关键机制。绝对位置编码(Absolute P…...

PostgreSQL 数据库备份与还原
为了安全与数据共享等,创建好的数据库有时候需要备份操作和还原操作。数据库的备份与还原主要是三个命令:pg_dump、pg_dumpall 和 pg_restore 。 其中pg_dump用于备份单个数据库,它支持多种备份格式(SQL、自定义等)&a…...

proxmox通过更多的方式创建虚拟机
概述 作为一名资深运维工程师,我们经常需要在 Proxmox 虚拟化平台上创建和管理虚拟机。本文将介绍三种不同的方式在 Proxmox 上创建 Ubuntu 虚拟机: 通过 Proxmox 命令创建虚拟机通过 Shell 脚本自动化创建虚拟机使用 Proxmox API 创建虚拟机 每种方式…...

WordPress使用(2)
上一篇文章讲述了WordPress的基本安装,主要是docker方式的处理。本文章主要介绍WordPress安装后的其他设置。 1. 安装后设置 安装后碰到的第一个需求就是安装一个合适的主题,但WordPress默认的上传文件大小是2M,远远无法满足要求࿰…...
git中文件的状态状态切换
文件的状态分类 Git 中文件的状态主要分为以下几种: Untracked(未跟踪) 定义:这些文件从未被 Git 跟踪过,通常是因为它们是新创建的文件,或者被 .gitignore 排除在外。 示例:新创建的文件 new…...
解决php8.3无法加载curl扩展
把它的值更改为扩展存在的目录的绝对路径(扩展存在的目录为有php_xxx.dll存在的目录) extension_dir "e:\serv\php83\ext" 然后从php根目录复制 libssh2.dll 和 libcrypto-*.dll 和 libssl-*.dll 到Apache根目录下的bin目录 重启apache服务即可...
三路排序算法
三路排序算法 引言 排序算法是计算机科学中基础且重要的算法之一。在数据分析和处理中,排序算法的效率直接影响着程序的执行速度和系统的稳定性。本文将深入探讨三路排序算法,包括其原理、实现和应用场景。 一、三路排序算法的原理 三路排序算法是一…...

入行FPGA设计工程师需要提前学习哪些内容?
FPGA作为一种灵活可编程的硬件平台,广泛应用于嵌入式系统、通信、数据处理等领域。很多人选择转行FPGA设计工程师,但对于新手来说,可能在学习过程中会遇到一些迷茫和困惑。为了帮助大家更好地准备,本文将详细介绍入行FPGA设计工程…...

DBASE DBF数据库文件解析
基于Java实现DBase DBF文件的解析和显示 JDK19编译运行,实现了数据库字段和数据解析显示。 首先解析数据库文件头代码 byte bytes[] Files.readAllBytes(Paths.get(file));BinaryBufferArray bis new BinaryBufferArray(bytes);DBF dbf new DBF();dbf.VersionN…...

html基本结构和常见元素
html5文档基本结构 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><title>文档标题</title> </head> <body>文档正文部分 </body> </html> html文档可分为文档头和文档体…...

JAVAweb学习日记(十) Mybatis入门操作
一、介绍 二、快速入门程序 三、入门-数据库连接池 四、入门-lombok工具包...

Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...

Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...

HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...

Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...

JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
CppCon 2015 学习:Time Programming Fundamentals
Civil Time 公历时间 特点: 共 6 个字段: Year(年)Month(月)Day(日)Hour(小时)Minute(分钟)Second(秒) 表示…...