【设计模式】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年自研的新一代一站式协作平台,将即时沟通、日历、云文档、云盘和工作台深度整合,通过开放兼容的平台,让成员在一处即可实现高效的沟通和流畅的协作,全方位提升企业效率。 …...

06 科技英语|控制与优化学科词汇
maneuver n 策略;v 操控、调遣 manipulate vt 熟练控制 scalability n 可扩展性 leverage n 杠杆;v 促使...改变 flexibility n 弹性 dispatch n 急件;v 调度;派遣 leverage …...

【网络教程】GitHub搜索技巧大揭秘
文章目录 1. 使用关键词优化搜索2. 结合布尔运算符3. 利用星号扩展搜索4. 高级搜索语法5. 按照星标数量搜索6. 使用文件类型搜索7. 在特定分支上搜索8. 使用文件名搜索9. 搜索贡献者10. 使用标签筛选仓库在开发过程中,我们经常需要在GitHub上查找代码、库或相关文档。本文将介…...

AUTOSAR LIN: LDF(LIN Description File)文件解析
LDF文件示例 LIN_description_file "lin_example.ldf" { LIN_protocol_version "2.0";LIN_language_version "2.0";nodes {master: MasterNode;slaves: SlaveNode1, SlaveNode2;};signals {Signal1: MasterNode, SlaveNode1;Signal2: Maste…...

Vue.js 报错:Cannot read property ‘validate‘ of undefined“
错误解决 起因,是我将elemnt-ui登录,默认放在mounted()函数里面,导致vue初始化就调用这个函数。 找了网上,有以下错误原因: 1.一个是你ref写错了,导致获取不了这个表单dom,我这显然不是。 2.…...

vue使用wangEditor
vue版本2.0;editor5.1.23版本;editor-for-vue:1.0.2版本 api文档入口 效果图 安装步骤入口 npm install wangeditor/editor --savenpm install wangeditor/editor-for-vue --save代码 <template><div><div style"bor…...

网络编程、socket编程、多进程并发服务器
网络编程 一、TCP编程的API socket: int socket(int domain, int type, int protocol); 返回值:> 0 代表函数调用成功,这个值是一个文件描述符< 0 代表函数调用失败 int domain:地址簇 AF_INET:IPv4 AF_INET6: IPv6 i…...

Elasticsearch:自动使用服务器时间设置日期字段并更新时区
在大多数情况下,你的数据包含一个以 create_date 命名的字段。 即使没有日期字段,处理各种格式和时区的日期对数据仓库来说也是一个重大挑战。 与此类似,如果要检测变化的数据,则必须准确设置日期字段。 在 Elasticsearch 中还有…...

网络技术三:局域网基本原理
局域网基本原理 使用的协议及线缆 物理层 双绞线 同轴电缆 光纤 无线电 数据链路层 以太网 唯一事实标准 令牌环 淘汰 FDDI 光纤分布式接口 网络层 IP 唯一的事实标准 IPX 淘汰 Apple talk 淘汰 局域网设备 集线器 内部为总线型拓扑 任意时间只能由一台主机占用总线&a…...

Fine-tuning Large Enterprise Language Models via Ontological Reasoning
本文是LLM系列文章,针对《Fine-tuning Large Enterprise Language Models via Ontological Reasoning》的翻译。 基于本体论推理的大型企业语言模型微调 摘要1 引言2 微调LLM的神经符号管道3 通过概念证明进行初步验证4 结论 摘要 大型语言模型(LLM&am…...

2023年全国职业院校技能大赛 高等职业教育组(信息安全管理与评估)正式赛题
全国职业院校技能大赛 高等职业教育组 qq:2366046367 q群:670610200信息安全管理与评估 任务书 模块一 网络平台搭建与设备安全防护 一、 比赛时间 本阶段比赛时长为180分钟。 二、 赛项信息 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 第一阶段 网络平台搭建与设备安全防护 …...