C++设计模式-Builder 构建器

通过“对象创建” 模式绕开new,来避免对象创建(new)过程中所导致的紧耦合(依赖具体类),从而支持对象创建的稳定。它是接口抽象之后的第一步工作。

一、动机

  • 在软件系统中,有时候面临着“一个复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定

  • 如何应对这种变化?如何提供一种 “封装机制”来隔离出“复杂对象的各个部分”的变化,从而保持系统中的“稳定构建算法”不随着需求改变而改变?

二、模式定义

将一个复杂对象的构建与其表示相分离,使得同样的构建过
程(稳定)可以创建不同的表示(变化)。
——《设计模式》GoF

三、代码示例

我们以房屋为例来展示建造者模式的应用。House类代表房屋对象,而HouseBuilder抽象类定义了构建房屋的步骤。StoneHouseBuilderHouseBuilder的具体实现,用于构建石头房屋。HouseDirector类负责指导具体建造者对象的构建过程。

通过使用建造者模式,我们可以将房屋对象的构建逻辑与客户端代码分离开来。客户端只需要创建一个合适的具体建造者对象,并将其传递给指导者进行构建。这样可以使客户端代码更简洁、可读性更高,并且在需要构建不同类型的房屋时更加灵活和扩展。

#include <iostream>class House {
public:void SetFoundation(const std::string& foundation) {this->foundation = foundation;}void SetWalls(const std::string& walls) {this->walls = walls;}void SetRoof(const std::string& roof) {this->roof = roof;}void SetDoors(const std::string& doors) {this->doors = doors;}void SetWindows(const std::string& windows) {this->windows = windows;}void Show() {std::cout << "房屋部分:" << std::endl;std::cout << "地基:" << foundation << std::endl;std::cout << "墙壁:" << walls << std::endl;std::cout << "屋顶:" << roof << std::endl;std::cout << "门:" << doors << std::endl;std::cout << "窗户:" << windows << std::endl;}private:std::string foundation;  // 地基std::string walls;       // 墙壁std::string roof;        // 屋顶std::string doors;       // 门std::string windows;     // 窗户
};class HouseBuilder {
public:virtual ~HouseBuilder() {}House* GetResult() {return pHouse;}virtual void BuildFoundation() = 0;  // 构建地基virtual void BuildWalls() = 0;       // 构建墙壁virtual void BuildRoof() = 0;        // 构建屋顶virtual void BuildDoors() = 0;       // 构建门virtual void BuildWindows() = 0;     // 构建窗户protected:House* pHouse;
};class StoneHouseBuilder : public HouseBuilder {
public:StoneHouseBuilder() {pHouse = new House();}void BuildFoundation() override {pHouse->SetFoundation("石头地基");}void BuildWalls() override {pHouse->SetWalls("石头墙壁");}void BuildRoof() override {pHouse->SetRoof("石头屋顶");}void BuildDoors() override {pHouse->SetDoors("木门");}void BuildWindows() override {pHouse->SetWindows("玻璃窗户");}
};class HouseDirector {
public:HouseDirector(HouseBuilder* builder) {pHouseBuilder = builder;}House* Construct() {pHouseBuilder->BuildFoundation();  // 构建地基pHouseBuilder->BuildWalls();       // 构建墙壁pHouseBuilder->BuildRoof();        // 构建屋顶pHouseBuilder->BuildDoors();       // 构建门pHouseBuilder->BuildWindows();     // 构建窗户return pHouseBuilder->GetResult();}private:HouseBuilder* pHouseBuilder;
};int main() {HouseBuilder* builder = new StoneHouseBuilder();  // 使用石头房屋构建器HouseDirector director(builder);House* house = director.Construct();  // 构建房屋house->Show();  // 展示房屋部分delete house;delete builder;return 0;
}

输出:

房屋部分:
地基:石头地基
墙壁:石头墙壁
屋顶:石头屋顶
门:木门
窗户:玻璃窗户

这时候,假如我们有新需求,需要造一个黄金打造的房子,这时候就很方便了,只需要增加GoldenHouseBuilder 建造器,就可以完成这个扩展,不需要更改以前的代码,满足开放-封闭原则

class GoldenHouseBuilder : public HouseBuilder {
public:GoldenHouseBuilder() {pHouse = new House();}void BuildFoundation() override {pHouse->SetFoundation("黄金地基");}void BuildWalls() override {pHouse->SetWalls("黄金墙壁");}void BuildRoof() override {pHouse->SetRoof("黄金屋顶");}void BuildDoors() override {pHouse->SetDoors("金门");}void BuildWindows() override {pHouse->SetWindows("钻石窗户");}
};

调用过程

    HouseBuilder* goldenBuilder = new GoldenHouseBuilder();  // 使用黄金房屋构建器HouseDirector goldenDirector(goldenBuilder);House* goldenHouse = goldenDirector.Construct();  // 构建黄金房屋goldenHouse->Show();  // 展示黄金房屋部分delete goldenHouse;delete goldenBuilder;

房屋部分:
地基:黄金地基
墙壁:黄金墙壁
屋顶:黄金屋顶
门:金门
窗户:钻石窗户

四、结构

在这里插入图片描述

五、总结

在软件开发过程中,有时候需要构建具有复杂结构的对象。如果直接在客户端代码中创建和配置这些对象,会导致代码变得复杂且难以维护。此外,如果要构建多个具有不同配置的相似对象,每次都重复编写相似的构建代码也是低效的。为了解决这些问题,可以使用建造者模式。

建造者模式的核心思想是将对象的构建过程从其表示中分离出来。它允许你使用相同的构建过程来创建不同的表示形式。该模式将对象的构建委托给一个单独的建造者对象,该对象负责构建对象的各个部分,并最后返回构建好的对象。

在示例代码中,我们以房屋为例来展示建造者模式的应用。House类代表房屋对象,而HouseBuilder抽象类定义了构建房屋的步骤。StoneHouseBuilderGoldenHouseBuilderHouseBuilder的具体实现,分别用于构建石头房屋和黄金房屋。HouseDirector类负责指导具体建造者对象的构建过程。

通过使用建造者模式,我们可以将房屋对象的构建逻辑与客户端代码分离开来。客户端只需要创建一个合适的具体建造者对象,并将其传递给指导者进行构建。这样可以使客户端代码更简洁、可读性更高,并且在需要构建不同类型的房屋时更加灵活和扩展。

建造者模式适用于构建复杂对象的情况,将构建逻辑与表示分离,使得构建过程更加灵活和可扩展。它提供了一种组织和管理对象构建的方式,避免了繁琐和重复的构建代码。通过委托具体的建造者对象来构建对象,客户端代码可以专注于高级操作,而无需关心对象的内部构建细节。

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

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

相关文章

Spark基础入门

spark基础入门 环境搭建 localstandlonespark ha spark code spark corespark sqlspark streaming 环境搭建 准备工作 创建安装目录 mkdir /opt/soft cd /opt/soft下载scala wget https://downloads.lightbend.com/scala/2.13.12/scala-2.13.12.tgz -P /opt/soft解压scala…

单元测试计划、用例、报告、评审编制模板

单元测试支撑文档编制模板&#xff0c;具体文档如下&#xff1a; 1. 单元测试计划 2. 单元测试用例 3. 单元测试报告 4. 编码及测试评审报告 软件项目相关资料全套获取&#xff1a;软件项目开发全套文档下载-CSDN博客 1、单元测试计划 2、单元测试用例 3、单元测试报告 4、编码…

FastSAM 分割一切 速度可以比 SAM 快 50 倍

一、FastSAM 在自然语言处理领域有 ChatGPT 通用大语言模型系列&#xff0c;但是在图像领域好像一直没有通用领域模型&#xff0c;但MetaAI 提出能够 分割一切 的视觉基础大模型 SAM 可以做到很好的分割效果&#xff0c;并且不限于场景、不限于目标&#xff0c;为探索视觉大模…

四. 基于环视Camera的BEV感知算法-BEVDet

目录 前言0. 简述1. 算法动机&开创性思路2. 主体结构3. 损失函数4. 性能对比总结下载链接参考 前言 自动驾驶之心推出的《国内首个BVE感知全栈系列学习教程》&#xff0c;链接。记录下个人学习笔记&#xff0c;仅供自己参考 本次课程我们来学习下课程第四章——基于环视Cam…

Java系列-HashMap构造方法

1.无参 只初始化了loadFactor public class HashMap<K,V> extends AbstractMap<K,V>implements Map<K,V>, Cloneable, Serializable {final float loadFactor;public HashMap() {this.loadFactor DEFAULT_LOAD_FACTOR; // all other fields defaulted} }2…

Android动画

关于作者&#xff1a;CSDN内容合伙人、技术专家&#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 &#xff0c;擅长java后端、移动开发、商业变现、人工智能等&#xff0c;希望大家多多支持。 目录 一、导读二、概览三、动画实现3.1 帧动画资源文件中实现…

【MySQL】触发器trigger / 事件

文章目录 1. 触发器 trigger1.1 触发器命名1.2 new和old关键字1.3 案例&#xff1a;insert 触发器1.4 练习&#xff1a;delete 触发器1.5 查看触发器 show triggers1.6 使用触发器记录对表的操作 2 事件2.1 打开 / 关闭事件调度器2.2 创建事件 create event2.3 查看&#xff0c…

软件设计师——数据结构(二)

&#x1f4d1;前言 本文主要是【数据结构】——软件设计师——数据结构的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304…

5个免费、跨平台的SQLite数据库可视化工具

前言 SQLite是一个轻量级的嵌入式关系型数据库&#xff0c;目前最新的版本是 SQLite3。今天推荐5个实用的SQLite数据库可视化工具(GUI)&#xff0c;帮助大家更好的管理SQLite数据库。 什么是SQLite&#xff1f; SQLite是一个轻量级的嵌入式关系型数据库&#xff0c;它以一个…

dp中最短编辑距离的笔记(分析dp)

dp分析往往就是看最后一步的变化。 分析&#xff1a; 设a串长度为i&#xff0c;b串长度为j。题目要求为通过三种操作将a字符串转化为b字符串的最少次数。 删除操作&#xff1a; 把a[i]删除后a[1~i]和b[1~j]匹配&#xff0c;所以可以得到f[i - 1][j] 1&#xff0c;在此之前要先…

连锁管理系统是什么?有哪些功能?

连锁管理系统帮助门店实现POS收银管理、门店管理、采购订货管理、线上商城搭建、供应链管理一体化管理系统&#xff0c;快速提高门店管理效率&#xff0c;无论你的门店有多少&#xff0c;连锁总部都能通过系统随时洞察监管门店的所有运营数据。 连锁管理系统由&#xff1a;1个…

Eslint 要被 Oxlint替换了吗

什么是 Oxlint 由于最近的rust在前端领域的崛起,基于rust的前端生态链遭到rust底层重构,最近又爆出OxLint,是一款基于Rust的linter工具。Oxlint在国外前端圈引起热烈讨论,很多大佬给出了高度评价。 事实上,Oxlint 是 Oxc 项目旗下的一款产品,专为 JavaScript 和 TypeSc…

Java解决不同路径问题

Java解决不同路径问题 01 题目 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有多少…

linux修改mysql默认端口(很明智的选择因为后面会遇到各种问题)

1. 登录到mysql查看当前的端口号&#xff1a; show global variables like ‘port’; 2.编辑/etc/my.conf 文件添加port3506 这样的样式 保存退出&#xff1b; 内容: mysqld] port3506 datadir/var/lib/mysql socket/var/lib/mysql/mysql.sock usermysql # Disabling sy…

【CMU 15-445】Lecture 10: Sorting Aggregations Algorithms 学习笔记

Sorting & Aggregations Algorithms SortingTop-N Heap SortExternal Merge Sort2-WAY External Merge SortK-WAY External Merge SortDouble Buffering Optimization AggregationsSortingHashing 本节课主要介绍的是数据库系统中的排序算法以及聚合算法 Sorting 排序算法…

【TB作品】51单片机 实物+仿真-电子拔河游戏_亚博 BST-M51

代码工程。 http://dt4.8tupian.net/2/28880a66b12880.pg3这段代码是用于一个数字拔河游戏的嵌入式系统&#xff0c;采用了基于8051架构的单片机&#xff0c;使用Keil C51编译器。 主要功能包括&#xff1a; 数码管显示&#xff1a;使用了四个数码管&#xff08;通过P2的控制…

【华为数据之道学习笔记】5-4 数据入湖方式

数据入湖遵循华为信息架构&#xff0c;以逻辑数据实体为粒度入湖&#xff0c;逻辑数据实体在首次入湖时应该考虑信息的完整性。原则上&#xff0c;一个逻辑数据实体的所有属性应该一次性进湖&#xff0c;避免一个逻辑实体多次入湖&#xff0c;增加入湖工作量。 数据入湖的方式…

配置 vim 默认显示行号 行数 :set number

vi ~/.vimrc 最后添加一行 :set number保存退出&#xff0c;再次 vim 打开文件&#xff0c;默认就会显示行号了

Feign-实现Feign最佳实践

目录 一、实现最佳实践的步骤&#xff08;方式二&#xff09; 1.1 首先创建一个module&#xff0c;命名为feign-api&#xff0c;然后引入feign的starter依赖 1.2.将order-service中编写的UserClient、User、DefaultFeignConfiguration都复制到feign-api项目 1.3.在order-se…

Kali Linux安装Xrdp远程桌面工具结合内网穿透实现远程访问Kali桌面

文章目录 前言1. Kali 安装Xrdp2. 本地远程Kali桌面3. Kali 安装Cpolar 内网穿透4. 配置公网远程地址5. 公网远程Kali桌面连接6. 固定连接公网地址7. 固定地址连接测试 前言 Kali远程桌面的好处在于&#xff0c;它允许用户从远程位置访问Kali系统&#xff0c;而无需直接物理访…