【设计模式】Head First 设计模式——构建器模式 C++实现
设计模式最大的作用就是在变化和稳定中间寻找隔离点,然后分离它们,从而管理变化。将变化像小兔子一样关到笼子里,让它在笼子里随便跳,而不至于跳出来把你整个房间给污染掉。
设计思想
将一个复杂对象的构建与其表示相分离,使得同样的构建过程(稳定)可以创建不同的表示(变化)
动机
在软件系统中,有时候面临着“一个复杂对象” 的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定
如何应对这种变化,如何提供一种“封装机制”来隔离出“复杂对象的各个部分”的变化,从而保证系统中的“稳定构建算法”不随着需求改变而改变?
结构
要点总结
Builder 模式主要用于“分步骤构建一个复杂的对象”。在这其中“ 分步骤 ”是一个稳定的算法,而复杂对象的各个部分则经常变化
变化点在哪里,封装就在哪里 — Builder 模式主要在于应对“复杂对象各个部分”的频繁需求变动。其缺点在于难以应对“分步骤构建算法”的需求变动
在Builder 模式中,要注意不同语言中构造器内调用抽象方法的差别。
业务场景
假如你要建房子,建房子需要打地基,需要买建材垒墙,需要造窗户等等,构造一个“房子”对象似乎并不是一件简单的事情…而现在,需要你用不同建材的材料分别去建房子,这些过程一样,但是材料不一样,该如何设计?
代码案例
#include <iostream>
#include <memory>
#include <vector>
using namespace std;class House
{
public:House() {}~House(){cout << "拆房..." << endl;}void init(){build1();build2();if (build3()){for (int i = 0; i < 4; i++){build4(i);}}build5();}protected:virtual void build1() const = 0;virtual void build2() const = 0;virtual bool build3() const = 0;virtual void build4(const int i) const = 0;virtual void build5() const = 0;
};class storeHouse : public House
{
private:virtual void build1() const override{cout << "用石头打地基..." << endl;}virtual void build2() const override{cout << "用石头造房子..." << endl;}virtual bool build3() const override{return cout << "通过质检..." << endl, true;}virtual void build4(const int i) const override{cout << "造第" << (i + 1) << "扇窗户" << endl;}virtual void build5() const override{cout << "石头房子竣工..." << endl;}
};class glassHouse : public House
{
private:virtual void build1() const override{cout << "用玻璃打地基..." << endl;}virtual void build2() const override{cout << "用玻璃造房子..." << endl;}virtual bool build3() const override{return cout << "通过质检..." << endl, true;}virtual void build4(const int i) const override{cout << "造第" << (i + 1) << "扇窗户" << endl;}virtual void build5() const override{cout << "玻璃房子竣工..." << endl;}
};class treeHouse : public House
{
private:virtual void build1() const override{cout << "用木头打地基..." << endl;}virtual void build2() const override{cout << "用木头造房子..." << endl;}virtual bool build3() const override{return cout << "通过质检..." << endl, true;}virtual void build4(const int i) const override{cout << "造第" << (i + 1) << "扇窗户" << endl;}virtual void build5() const override{cout << "木头房子竣工..." << endl;}
};int main()
{std::vector<std::shared_ptr<House>> myHouse;myHouse.push_back(make_shared<storeHouse>());myHouse.push_back(make_shared<glassHouse>());myHouse.push_back(make_shared<treeHouse>());for (const auto& item : myHouse){item->init();cout << "-----------------------------" << endl;}return 0;
}
这里和之前的模板方法模式很像,但是这里把House中的部分属性忽略了,仅仅暴露出其建造过程,于是,如果采用构建器模式,可以单独把建造过程抽出来:
#include <iostream>
#include <memory>
#include <vector>
using namespace std;class House
{
public:House() {}~House(){cout << "拆房..." << endl;}public:virtual void build1() const = 0;virtual void build2() const = 0;virtual bool build3() const = 0;virtual void build4(const int i) const = 0;virtual void build5() const = 0;
};class storeHouse : public House
{
public:virtual void build1() const override{cout << "用石头打地基..." << endl;}virtual void build2() const override{cout << "用石头造房子..." << endl;}virtual bool build3() const override{return cout << "通过质检..." << endl, true;}virtual void build4(const int i) const override{cout << "造第" << (i + 1) << "扇窗户" << endl;}virtual void build5() const override{cout << "石头房子竣工..." << endl;}
};class glassHouse : public House
{
public:virtual void build1() const override{cout << "用玻璃打地基..." << endl;}virtual void build2() const override{cout << "用玻璃造房子..." << endl;}virtual bool build3() const override{return cout << "通过质检..." << endl, true;}virtual void build4(const int i) const override{cout << "造第" << (i + 1) << "扇窗户" << endl;}virtual void build5() const override{cout << "玻璃房子竣工..." << endl;}
};class treeHouse : public House
{
public:virtual void build1() const override{cout << "用木头打地基..." << endl;}virtual void build2() const override{cout << "用木头造房子..." << endl;}virtual bool build3() const override{return cout << "通过质检..." << endl, true;}virtual void build4(const int i) const override{cout << "造第" << (i + 1) << "扇窗户" << endl;}virtual void build5() const override{cout << "木头房子竣工..." << endl;}
};class HouseBuilder
{private:std::shared_ptr<House> _house;public:HouseBuilder(const std::shared_ptr<House>& _house): _house(_house){}void init(){_house->build1();_house->build2();if (_house->build3()){for (int i = 0; i < 4; i++){_house->build4(i);}}_house->build5();}
};int main()
{std::vector<std::shared_ptr<HouseBuilder>> myHouse;myHouse.push_back(make_shared<HouseBuilder>(make_shared<storeHouse>()));myHouse.push_back(make_shared<HouseBuilder>(make_shared<glassHouse>()));myHouse.push_back(make_shared<HouseBuilder>(make_shared<treeHouse>()));for (const auto& item : myHouse){item->init();cout << "-----------------------------" << endl;}return 0;
}
相关文章:

【设计模式】Head First 设计模式——构建器模式 C++实现
设计模式最大的作用就是在变化和稳定中间寻找隔离点,然后分离它们,从而管理变化。将变化像小兔子一样关到笼子里,让它在笼子里随便跳,而不至于跳出来把你整个房间给污染掉。 设计思想 将一个复杂对象的构建与其表示相分离&…...
基于Python+Django深度学习的身份证识别考勤系统设计与实现
摘 要 我们的生活都是由信息技术在潜移默化的改变着,那么早先改变校园生活的是校园信息化,改变社会人生活是各种应用软件。出行我们依靠的是滴滴,外卖我们依靠的是美团等等。从信息技术的发展至今,各色各样的技术能够满足各类人群…...
Unity控制程序退出
大家好,我是阿赵。 最近把公司的游戏发布到各种PC的游戏大厅,遇到了挺多奇怪的需求。之前介绍了一些Unity发布PC端控制窗口最大最小化、修改exe信息等问题,这次来探讨一下退出游戏的问题。 一、收到奇怪的需求 某游戏大厅要求࿰…...
C++ using的多种用法
1、引入命名空间 using namespace std; using std::cout; 2、引入基类成员 class Base{ public:void func(){cout << "Base::func()" << endl;} }; class Derived : public Base{ public:using Base::func;void func(int x){cout << "Deriv…...

Java环境的安装
最近博主也是在学校开始学习了Java,也通过老师知道了可以通过大学生学生证申(bai)请(piao) IDEA的企业版(社区版也是够学习用的)有很多同学还是没有搞懂便做一下分享。 🌱博客主页:青竹雾色间. 😘博客制作…...

【ES6】js中的__proto__和prototype
在JavaScript中,__proto__和prototype都是用于实现对象继承的关键概念。 1、proto __proto__是一个非标准的属性,用于设置或获取一个对象的原型。这个属性提供了直接访问对象内部原型对象的途径。对于浏览器中的宿主对象和大多数对象来说,可…...

工程项目管理系统源码-简洁+好用+全面-工程项目管理
工程项目管理系统是指从事工程项目管理的企业(以下简称工程项目管理企业)受业主委托,按照合同约定,代表业主对工程项目的组织实施进行全过程或若干阶段的管理和服务。 系统定义 工程项目管理企业不直接与该工程项目的总承包企…...

后端SpringBoot+前端Vue前后端分离的项目(二)
前言:完成一个列表,实现表头的切换,字段的筛选,排序,分页功能。 目录 一、数据库表的设计 编辑二、后端实现 环境配置 model层 mapper层 service层 service层单元测试 controller层 三、前端实现 interface接…...

【5】openGL使用宏和函数进行错误检测
当我们编写openGL程序,没有报编译链接错误,但是运行结果是黑屏,这不是我们想要的。 openGL提供了glGetError 来检查错误,我们可以通过在运行时进行打断点查看glGetError返回值,得到的是一个十进制数,将其转…...

STM32 CAN快速配置(HAL库版本)
STM32 CAN快速配置(HAL库版本) 目录 STM32 CAN快速配置(HAL库版本)前言1 软件编程1.1 初始化1.1.1 引脚设置1.1.2 CAN参数设置1.1.3 CAN滤波器设置 1.2 CAN发送1.3 CAN接收 2 运行测试结束语 前言 控制器局域网总线(CA…...

【文末送书】全栈开发流程——后端连接数据源(二)
前言 「作者主页」:雪碧有白泡泡 「个人网站」:雪碧的个人网站 「推荐专栏」: ★java一站式服务 ★ ★ React从入门到精通★ ★前端炫酷代码分享 ★ ★ 从0到英雄,vue成神之路★ ★ uniapp-从构建到提升★ ★ 从0到英雄ÿ…...

leetcode_27_最小栈
class MinStack { public:MinStack() {}void push(int val) {//只要是压栈,先将元素保存到_elem中_elem.push(val);//如果x小于_min中栈顶的元素,将x再压入_min中if(_min.empty() || val < _min.top()){_min.push(val);}}void pop() {//如果——min栈…...
01-ZooKeeper快速入门
1 Zookeeper概念 Zookeeper是Apache Hadoop项目下的一个子项目,是一个树形目录服务。 zookeeper翻译过来就是 动物园管理员,它是用来管理Hadoop(大象)、Hive(蜜蜂)、Pig(小猪)的管…...

[经典面试题]JS的typeof和instanceof区别
一、typeof typeof 是一个一元操作符不是函数,所以不需要传递参数,使用方法非常简单:typeof A 对于基本类型 let s "Nicholas"; let b true; let i 22; let u; let sb undefined; console.log(typeof s); // string console.…...

C++内存区堆和栈
在C中,内存分成5个区,堆、栈、自由存储区、全局/静态存储区和常量存储区。 栈,就是那些由编译器在需要的时候分配,在不需要的时候自动清除的变量的存储区。里面的变量通常是局部变量、函数参数等。 堆,就是那些…...

QT中闹钟的设置
.h文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPushButton> //按钮 #include <QTextEdit> //文本 #include <QLabel> //标签 #include <QLineEdit> //行编辑器#include <QTimerEvent> //定时器事件类头文件 #…...
【Redis】几款redis可视化工具(推荐Another Redis Desktop Manager)
Redis是一个超精简的基于内存的键值对数据库(key-value),一般对并发有一定要求的应用都用其储存session,乃至整个数据库。不过它公自带一个最小化的命令行式的数据库管理工具,有时侯使用起来并不方便。不过Github上面已经有了很多图形化的管理…...

肖sir__设计测试用例方法之因果图07_(黑盒测试)
设计测试用例方法之因果图 一、定义:因果图提供了一个把规格转化为判定表的系统化方法,从该图中可以产生测试数据。其 中,原因是表示输入条件,结果是对输入执 行的一系列计算后得到的输出。 二、因果图方法最终生成的就是判定表。…...

李宏毅-21-hw3:对11种食物进行分类-CNN
一、代码慢慢阅读理解总结内化: 1.关于torch.nn.covd2d()的参数含义、具体用法、功能: (1)参数含义: 注意,里面的“padding”参数:《both》side所以是上下左右《四》边都会加一个padding数量…...

成集云 | 飞书审批同步金蝶云星空销售订单 | 解决方案
源系统成集云目标系统 方案介绍 飞书是字节跳动于2016年自研的新一代一站式协作平台,将即时沟通、日历、云文档、云盘和工作台深度整合,通过开放兼容的平台,让成员在一处即可实现高效的沟通和流畅的协作,全方位提升企业效率。 …...

Unity3D中Gfx.WaitForPresent优化方案
前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...

【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...

376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...

热烈祝贺埃文科技正式加入可信数据空间发展联盟
2025年4月29日,在福州举办的第八届数字中国建设峰会“可信数据空间分论坛”上,可信数据空间发展联盟正式宣告成立。国家数据局党组书记、局长刘烈宏出席并致辞,强调该联盟是推进全国一体化数据市场建设的关键抓手。 郑州埃文科技有限公司&am…...
ubuntu22.04 安装docker 和docker-compose
首先你要确保没有docker环境或者使用命令删掉docker sudo apt-get remove docker docker-engine docker.io containerd runc安装docker 更新软件环境 sudo apt update sudo apt upgrade下载docker依赖和GPG 密钥 # 依赖 apt-get install ca-certificates curl gnupg lsb-rel…...

高端性能封装正在突破性能壁垒,其芯片集成技术助力人工智能革命。
2024 年,高端封装市场规模为 80 亿美元,预计到 2030 年将超过 280 亿美元,2024-2030 年复合年增长率为 23%。 细分到各个终端市场,最大的高端性能封装市场是“电信和基础设施”,2024 年该市场创造了超过 67% 的收入。…...

CSS 工具对比:UnoCSS vs Tailwind CSS,谁是你的菜?
在现代前端开发中,Utility-First (功能优先) CSS 框架已经成为主流。其中,Tailwind CSS 无疑是市场的领导者和标杆。然而,一个名为 UnoCSS 的新星正以其惊人的性能和极致的灵活性迅速崛起。 这篇文章将深入探讨这两款工具的核心理念、技术差…...
接口 RESTful 中的超媒体:REST 架构的灵魂驱动
在 RESTful 架构中,** 超媒体(Hypermedia)** 是一个核心概念,它体现了 REST 的 “表述性状态转移(Representational State Transfer)” 的本质,也是区分 “真 RESTful API” 与 “伪 RESTful AP…...
C/Python/Go示例 | Socket Programing与RPC
Socket Programming介绍 Computer networking这个领域围绕着两台电脑或者同一台电脑内的不同进程之间的数据传输和信息交流,会涉及到许多有意思的话题,诸如怎么确保对方能收到信息,怎么应对数据丢失、被污染或者顺序混乱,怎么提高…...