当前位置: 首页 > news >正文

C++设计模式之构造器

动机

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

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

代码示例:建立各种房子,比如砖瓦房,高楼,别墅等房子


class House{//....
};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;};class StoneHouse: public House{};// 石头房子的创建,override HouseBuilder里面的流程
class StoneHouseBuilder: public HouseBuilder{
protected:virtual void BuildPart1(){//pHouse->Part1 = ...;}virtual void BuildPart2(){}virtual void BuildPart3(){}virtual void BuildPart4(){}virtual void BuildPart5(){}};// 房子具体构建过程
class HouseDirector{public:// 有一个HouseBuilder的指针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();}
};int main() {// 创建石头房子的建造者StoneHouseBuilder stoneHouseBuilder;// 创建房子Director,并指定建造者HouseDirector houseDirector(&stoneHouseBuilder);// 构建房子House* stoneHouse = houseDirector.Construct();// 输出结果if (stoneHouse != nullptr) {// 假设 House 类有适当的输出方法// 这里只是简单示例,实际使用时需要根据具体类的实现调用相应的方法std::cout << "Stone House constructed." << std::endl;} else {std::cout << "Failed to construct Stone House." << std::endl;}// 释放资源delete stoneHouse;return 0;
}

上述代码涉及了Builder设计模式,包括以下几个类:

House 类:

表示待构建的产品,即房子。在示例中,StoneHouse 类是 House 的具体实现。

HouseBuilder 抽象类:

定义了构建产品(房子)的抽象接口。具体的建造者(例如 StoneHouseBuilder)需要继承这个抽象类并实现接口中的方法,以完成具体产品的构建。

StoneHouseBuilder 类:

HouseBuilder的具体实现,负责构建石头房子。它通过实现抽象接口中的方法来完成具体的建造流程。

HouseDirector 类:

起到指导建造的作用,通过构造函数接收一个具体的建造者对象。通过调用建造者的方法,按照一定的构建流程组织建造者完成产品的构建。
main 函数:

main 函数中,创建了 StoneHouseBuilder 的实例,然后创建了一个HouseDirector的实例,并将建造者传递给导演。通过导演的 Construct 方法,按照一定的构建流程构建了石头房子,并输出结果。
总体而言,Builder设计模式的目的是将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。在这个示例中,HouseBuilder 抽象类定义了构建房子的接口,StoneHouseBuilder 实现了具体的石头房子构建流程,而 HouseDirector 则负责协调建造者完成整个构建流程。

Builder要点总结

Builder 模式主要用于“分步骤构建一个复杂的对象”。在这其中“分步骤”是一个稳定的算法,而复杂对象的各个部分则经常变化。

变化点在哪里,封装哪里—— Builder模式主要在于应对“复杂对象各个部分”的频繁需求变动。其缺点在于难以应对“分步骤构建算法”的需求变动。

在Builder模式中,要注意不同语言中构造器内调用虚函数的差别(C++ vs. C#) 。

chatGPT给出的builder的例子

以下是一个简单的C++示例代码,演示Builder设计模式:

#include <iostream>
#include <string>// 产品类
class Product {
public:void AddPart(const std::string& part) {parts += part + " ";}void Show() const {std::cout << "Product Parts: " << parts << std::endl;}private:std::string parts;
};// 抽象建造者类
class Builder {
public:virtual void BuildPart1() = 0;virtual void BuildPart2() = 0;virtual Product* GetResult() = 0;
};// 具体建造者类
class ConcreteBuilder : public Builder {
public:ConcreteBuilder() {product = new Product();}void BuildPart1() override {product->AddPart("Part1");}void BuildPart2() override {product->AddPart("Part2");}Product* GetResult() override {return product;}private:Product* product;
};// 指导者类
class Director {
public:Director(Builder* builder) : builder(builder) {}void Construct() {builder->BuildPart1();builder->BuildPart2();}private:Builder* builder;
};int main() {// 创建具体建造者ConcreteBuilder concreteBuilder;// 创建指导者,并传入具体建造者Director director(&concreteBuilder);// 指导者构建产品director.Construct();// 获取最终产品Product* product = concreteBuilder.GetResult();// 展示产品if (product != nullptr) {product->Show();delete product;}return 0;
}

在这个示例中,Product 表示最终构建的复杂对象,Builder 是抽象建造者类,ConcreteBuilder 是具体建造者类,Director 是指导者类。通过指导者调用具体建造者的方法,最终得到构建完成的产品。这个例子中的产品是简单的包含两个部分的字符串,实际应用中可以根据需求定义更复杂的产品结构。

相关文章:

C++设计模式之构造器

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

红日靶场-5

环境搭建 这个靶场相对于前几个靶场来说较为简单&#xff0c;只有两台靶机&#xff0c;其中一台主机是win7&#xff0c;作为我们的DMZ区域的入口机&#xff0c;另外一台是windows2008&#xff0c;作为我们的域控主机&#xff0c;所以我们只需要给我们的win7配置两张网卡&#…...

做异端中的异端 -- Emacs裸奔之路3: 上古神键Hyper

谈一下快捷捷冲突的问题。 Emacs几乎穷尽所有组合键 我用下面命令&#xff0c;在Fundamental模式下&#xff0c;枚举所有绑定。 (defun keymap-lookup-test-fn(); printable keys(setq printable-chars (number-sequence 33 126))(setq i 0)(while (< i (length printable…...

Java多线程介绍及使用指南

“多线程”&#xff1a;并发 要介绍线程&#xff0c;首先要区分开程序、进程和线程这三者的区别。 程序&#xff1a;具有一定功能的代码的集合&#xff0c;但是是静态的&#xff0c;没有启动运行 进程&#xff1a;启动运行的程序【资源的分配单位】 线程&#xff1a;进程中的…...

HarmonyOS 5.0应用开发——列表(List)

【高心星出品】 文章目录 列表&#xff08;List&#xff09;列表介绍列表布局设置主轴方向设置交叉轴方向 列表填充分组列表填充 滚动条位置设置滚动位置滚到监听 列表项侧滑 列表&#xff08;List&#xff09; 列表介绍 列表作为一种容器&#xff0c;会自动按其滚动方向排列…...

自动化电气行业的优势和劣势是什么

优势 市场需求广泛&#xff1a; 自动化电气技术广泛应用于电力系统、制造业、交通、农业等多个领域&#xff0c;随着智能化、数字化趋势的加强&#xff0c;其市场需求持续增长。在智能制造、智能电网等领域&#xff0c;自动化电气技术更是发挥着关键作用&#xff0c;推动了行业…...

第 42 章 - Go语言 设计模式

在Go语言中&#xff0c;设计模式是一种被广泛接受的解决常见问题的最佳实践。这些模式可以分为三类&#xff1a;创建型模式、结构型模式和行为型模式。下面我将结合案例以及源代码对这三种类型的设计模式进行详细讲解。 创建型模式 创建型模式主要关注对象的创建过程&#xf…...

【机器学习】---大语言模型

引言&#xff1a;开启大语言模型的奇幻旅程 近年来&#xff0c;人工智能&#xff08;AI&#xff09;领域正在经历一场前所未有的技术革命&#xff0c;而其中最耀眼的明星莫过于大语言模型&#xff08;Large Language Models, LLMs&#xff09;。这些模型&#xff0c;犹如现代科…...

挑战用React封装100个组件【002】

项目地址 https://github.com/hismeyy/react-component-100 组件描述 组件适用于需要展示图文信息的场景&#xff0c;比如产品介绍、用户卡片或任何带有标题、描述和可选图片的内容展示 样式展示 代码展示 InfoCard.tsx import ./InfoCard.cssinterface InfoCardProps {t…...

MarkDown-插入图片-图片url地址的生成获取方法

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、url地址是什么二、如何获取图片的url地址1.了解图床2.使用图床获取图片URL地址2.1进入网站后&#xff0c;点击右下角“Select Image.”按钮&#xff0c;即可…...

插值、拟合和回归分析的相关知识

目录 0 序言 1 分段线性插值 2 多项式插值 3 样条插值 4 最小二乘拟合 5 多元线性回归 0 序言 在生产实践和科学研究中&#xff0c;常常有这些问题: 插值问题&#xff1a;由实验或测量得到变量间的一批离散样点&#xff0c;要求得到变量之间的函数关系或得到样点之外的…...

【小白学机器学习42】进行多次抽样,样本的分布参数和总体的分布参数的关系

目录 1 进行多次抽样&#xff0c;样本的分布参数和总体的分布参数的关系 2 样本容量越大&#xff0c;多次抽样的样本的分布参数和总体的分布参数的关系 3 随着样本容量增大&#xff0c;多次抽样均值的 平均值&#xff0c;方差的变化 4 随着样本容量增大&#xff0c;多次抽…...

链动星海 质引未来|中信银行加码科技金融 “接力式”服务助力“新质生产力”释放

11月26日&#xff0c;第二届中国国际供应链促进博览会&#xff08;以下简称链博会&#xff09;在北京中国国际展览中心开幕。中信集团以“链动星海 质引未来”为主题&#xff0c;亮相先进制造链展区。此次布展由中信金控主办、中信银行承办&#xff0c;携手中信证券、中信建投证…...

黑马2024AI+JavaWeb开发入门Day02-JS-VUE飞书作业

视频地址&#xff1a;哔哩哔哩 讲义作业飞书地址&#xff1a;飞书 一、作业1 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge">&l…...

云计算基础-期末复习

第一章&#xff1a;云计算概论 一、云计算的定义与特征 1. 定义&#xff1a; 云计算是一种通过网络以按需、可扩展的方式获取计算资源和服务的模式。它将计算资源视为一种公用事业&#xff0c;用户可以根据需求动态获取和释放资源&#xff0c;而无需了解底层基础设施的细节。…...

Java GET请求 请求参数在Body中使用Json格式传参

业务需要调个三方接口 使用GET请求方式 但是&#xff01;请求参数不在Query中&#xff0c;竟然在Body中&#xff0c;使用Json格式传参 在API调试工具里面可以调通 在java代码里&#xff0c;死活调不通 网上搜了搜&#xff0c;找到一个靠谱的&#xff0c;记录一下 import o…...

AI数据分析工具(一)

Looker Studio&#xff08;谷歌&#xff09;-免费 优点 免费使用&#xff1a;对于中小型企业和个人用户来说&#xff0c;没有任何费用压力&#xff0c;可以免费享受到数据可视化和报表创建的功能。与Google服务集成&#xff1a;特别适合使用Google产品生态的企业&#xff0c;…...

go结构体匿名“继承“方法冲突时继承优先顺序

在 Go 语言中&#xff0c;匿名字段&#xff08;也称为嵌入字段&#xff09;可以用来实现继承的效果。当你在一个结构体中匿名嵌入另一个结构体时&#xff0c;嵌入结构体的方法会被提升到外部结构体中。这意味着你可以直接通过外部结构体调用嵌入结构体的方法。 如果多个嵌入结…...

【049】基于51单片机语音录放【Proteus仿真+Keil程序+报告+原理图】

☆、设计硬件组成&#xff1a;51单片机最小系统ISD4004语音芯片LM386音频放大器喇叭LCD1602液晶显示按键控制LED灯。 1、本设计采用STC89C51/52、AT89C51/52、AT89S51/52作为主控芯片&#xff0c;LCD1602液晶显示屏实时显示&#xff1b; 2、系统具有两种模式&#xff1a;录音…...

《软件项目管理》期末-复习题及参考答案

&#xff08;1&#xff09;赶工一个任务时&#xff0c;你应该关注&#xff08; C &#xff09; A. 尽可能多的任务 B. 非关键任务 C. 加速执行关键路径上的任务 D. 通过成本最低化加速执行任务 &#xff08;2&#xff09;下列哪个不是项目管理计划的一部分&#xff1f;&#x…...

java_网络服务相关_gateway_nacos_feign区别联系

1. spring-cloud-starter-gateway 作用&#xff1a;作为微服务架构的网关&#xff0c;统一入口&#xff0c;处理所有外部请求。 核心能力&#xff1a; 路由转发&#xff08;基于路径、服务名等&#xff09;过滤器&#xff08;鉴权、限流、日志、Header 处理&#xff09;支持负…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…...

GitFlow 工作模式(详解)

今天再学项目的过程中遇到使用gitflow模式管理代码&#xff0c;因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存&#xff0c;无论是github还是gittee&#xff0c;都是一种基于git去保存代码的形式&#xff0c;这样保存代码…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台

淘宝扭蛋机小程序系统的开发&#xff0c;旨在打造一个互动性强的购物平台&#xff0c;让用户在购物的同时&#xff0c;能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机&#xff0c;实现旋转、抽拉等动作&#xff0c;增…...

LangFlow技术架构分析

&#x1f527; LangFlow 的可视化技术栈 前端节点编辑器 底层框架&#xff1a;基于 &#xff08;一个现代化的 React 节点绘图库&#xff09; 功能&#xff1a; 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...

LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)

在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...