C++创建型模式之生成器模式
解决的问题
生成器模式(Builder Pattern)主要解决复杂对象的构建问题。当一个对象的创建过程非常复杂,涉及多个步骤和多个部件时,使用生成器模式可以将对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。
适用场景
- 复杂对象的构建:当对象的构建过程非常复杂,涉及多个步骤和多个部件时。
- 不同的构建过程:当需要不同的表示时,可以使用相同的构建过程。
- 逐步构建:当对象的构建过程可以逐步进行时。
模式的参与者角色
- Builder(生成器接口):定义构建产品的各个部件的抽象接口。
- ConcreteBuilder(具体生成器):实现
Builder
接口,负责构建产品的各个部件。 - Product(产品):表示正在构建的复杂对象。
- Director(指导者):使用
Builder
接口来构建产品。
以生产汽车为例的生成器模式示例代码
#include <iostream>
#include <string>// 产品类:汽车
class Car {
public:void setBody(const std::string& body) { body_ = body; }void setEngine(const std::string& engine) { engine_ = engine; }void setWheels(const std::string& wheels) { wheels_ = wheels; }void setInterior(const std::string& interior) { interior_ = interior; }void show() const {std::cout << "Car Configuration: " << std::endl;std::cout << "Body: " << body_ << std::endl;std::cout << "Engine: " << engine_ << std::endl;std::cout << "Wheels: " << wheels_ << std::endl;std::cout << "Interior: " << interior_ << std::endl;}private:std::string body_;std::string engine_;std::string wheels_;std::string interior_;
};// 抽象生成器接口
class CarBuilder {
public:virtual ~CarBuilder() {}virtual void buildBody() = 0;virtual void buildEngine() = 0;virtual void buildWheels() = 0;virtual void buildInterior() = 0;virtual Car* getCar() = 0;
};// 具体生成器:SUV 汽车
class SUVBuilder : public CarBuilder {
public:SUVBuilder() { car_ = new Car(); }~SUVBuilder() { delete car_; }void buildBody() override { car_->setBody("SUV Body"); }void buildEngine() override { car_->setEngine("SUV Engine"); }void buildWheels() override { car_->setWheels("SUV Wheels"); }void buildInterior() override { car_->setInterior("SUV Interior"); }Car* getCar() override { return car_; }private:Car* car_;
};// 具体生成器:Sedan 汽车
class SedanBuilder : public CarBuilder {
public:SedanBuilder() { car_ = new Car(); }~SedanBuilder() { delete car_; }void buildBody() override { car_->setBody("Sedan Body"); }void buildEngine() override { car_->setEngine("Sedan Engine"); }void buildWheels() override { car_->setWheels("Sedan Wheels"); }void buildInterior() override { car_->setInterior("Sedan Interior"); }Car* getCar() override { return car_; }private:Car* car_;
};// 指导者
class Director {
public:void setBuilder(CarBuilder* builder) { builder_ = builder; }Car* constructCar() {builder_->buildBody();builder_->buildEngine();builder_->buildWheels();builder_->buildInterior();return builder_->getCar();}private:CarBuilder* builder_;
};// 客户端代码
int main() {Director director;// 创建 SUVstd::cout << "Building SUV..." << std::endl;SUVBuilder suvBuilder;director.setBuilder(&suvBuilder);Car* suv = director.constructCar();suv->show();delete suv;// 创建 Sedanstd::cout << "\nBuilding Sedan..." << std::endl;SedanBuilder sedanBuilder;director.setBuilder(&sedanBuilder);Car* sedan = director.constructCar();sedan->show();delete sedan;return 0;
}
代码说明
- Car 类表示正在构建的汽车产品,包含汽车的各个部件。
- CarBuilder 是一个抽象生成器接口,定义了构建汽车各个部件的方法和一个获取最终产品的接口。
- SUVBuilder 和 SedanBuilder 是具体生成器类,分别实现了
CarBuilder
接口,用于构建 SUV 和 Sedan 汽车。 - Director 类负责使用
CarBuilder
接口来构建汽车。它通过调用生成器的各个构建方法来逐步构建汽车。 - Client 在
main
函数中使用Director
和具体生成器来构建不同类型的汽车,并展示汽车配置。
总结
生成器模式通过将复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。在需要逐步构建复杂对象或需要不同表示的场景中,生成器模式非常有用。
模板方法(Template Method)模式与生成器(Builder)模式
形式相似点
- 抽象类与具体类:两种模式都涉及抽象类(或接口)和具体实现类。
- 分步构建:都需要分步骤构建复杂对象或执行算法。
目的的不同点
- 模板方法模式:定义一个算法的框架,允许子类在不改变算法结构的情况下重新定义算法的某些步骤。目的是为了代码复用和算法的一致性。
- 生成器模式:将复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。目的是为了构建复杂对象时的灵活性和可扩展性。
模板方法模式的代码示例
#include <iostream>
#include <string>// 抽象类,定义模板方法
class AbstractClass {
public:// 模板方法void templateMethod() {step1();step2();step3();}protected:virtual void step1() = 0;virtual void step2() = 0;virtual void step3() = 0;
};// 具体类1
class ConcreteClass1 : public AbstractClass {
protected:void step1() override {std::cout << "ConcreteClass1: Step 1" << std::endl;}void step2() override {std::cout << "ConcreteClass1: Step 2" << std::endl;}void step3() override {std::cout << "ConcreteClass1: Step 3" << std::endl;}
};// 具体类2
class ConcreteClass2 : public AbstractClass {
protected:void step1() override {std::cout << "ConcreteClass2: Step 1" << std::endl;}void step2() override {std::cout << "ConcreteClass2: Step 2" << std::endl;}void step3() override {std::cout << "ConcreteClass2: Step 3" << std::endl;}
};// 客户端代码
int main() {AbstractClass* class1 = new ConcreteClass1();class1->templateMethod();delete class1;std::cout << std::endl;AbstractClass* class2 = new ConcreteClass2();class2->templateMethod();delete class2;return 0;
}
生成器模式的代码示例
#include <iostream>
#include <string>// 产品类
class Product {
public:void setPartA(const std::string& partA) { partA_ = partA; }void setPartB(const std::string& partB) { partB_ = partB; }void setPartC(const std::string& partC) { partC_ = partC; }void show() const {std::cout << "Product parts: " << partA_ << ", " << partB_ << ", " << partC_ << std::endl;}private:std::string partA_;std::string partB_;std::string partC_;
};// 抽象生成器接口
class Builder {
public:virtual ~Builder() {}virtual void buildPartA() = 0;virtual void buildPartB() = 0;virtual void buildPartC() = 0;virtual Product* getProduct() = 0;
};// 具体生成器
class ConcreteBuilder : public Builder {
public:ConcreteBuilder() { product_ = new Product(); }~ConcreteBuilder() { delete product_; }void buildPartA() override { product_->setPartA("PartA"); }void buildPartB() override { product_->setPartB("PartB"); }void buildPartC() override { product_->setPartC("PartC"); }Product* getProduct() override { return product_; }private:Product* product_;
};// 指导者
class Director {
public:void setBuilder(Builder* builder) { builder_ = builder; }Product* constructProduct() {builder_->buildPartA();builder_->buildPartB();builder_->buildPartC();return builder_->getProduct();}private:Builder* builder_;
};// 客户端代码
int main() {Director director;// 创建具体生成器ConcreteBuilder builder;director.setBuilder(&builder);// 构建产品Product* product = director.constructProduct();product->show();delete product;return 0;
}
代码说明
模板方法示例
- AbstractClass:定义了一个模板方法
templateMethod()
,其中包含了三个抽象步骤step1()
,step2()
,step3()
。 - ConcreteClass1 和 ConcreteClass2:具体子类,分别实现了抽象步骤,但模板方法的结构保持不变。
- 客户端代码:通过创建
ConcreteClass1
和ConcreteClass2
的对象,调用templateMethod()
方法来执行算法,子类可以在不改变算法结构的情况下重新定义算法的某些步骤。
生成器模式示例
- Product:表示正在构建的复杂对象。
- Builder:抽象生成器接口,定义了构建产品的各个部件的方法和一个获取最终产品的接口。
- ConcreteBuilder:具体生成器类,实现了
Builder
接口,负责构建产品的各个部件。 - Director:指导者类,使用
Builder
接口来构建产品。通过调用生成器的各个构建方法来逐步构建产品。 - 客户端代码:通过
Director
和ConcreteBuilder
来构建产品,并展示产品配置。
总结
- 模板方法模式:目的是为了代码复用和算法的一致性,通过定义算法的框架,允许子类在不改变算法结构的情况下重新定义算法的某些步骤。
- 生成器模式:目的是为了构建复杂对象时的灵活性和可扩展性,通过将复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。
相关文章:
C++创建型模式之生成器模式
解决的问题 生成器模式(Builder Pattern)主要解决复杂对象的构建问题。当一个对象的创建过程非常复杂,涉及多个步骤和多个部件时,使用生成器模式可以将对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表…...

鸿蒙NEXT应用示例:切换图片动画
【引言】 在鸿蒙NEXT应用开发中,实现图片切换动画是一项常见的需求。本文将介绍如何使用鸿蒙应用框架中的组件和动画功能,实现不同类型的图片切换动画效果。 【环境准备】 电脑系统:windows 10 开发工具:DevEco Studio NEXT B…...
postgresql(功能最强大的开源数据库)继承特性和分区实现
PostgreSQL实现了表继承,在多重表继承下,对上亿条不同类别的数据条目进行按型号、按月份双层分区管理,既可在总表查阅所有条目的共有字段,也可在各类型字表查询附加字段,非常高效。 分区是通过继承的方式来实现的&…...

论文笔记(五十六)VIPose: Real-time Visual-Inertial 6D Object Pose Tracking
VIPose: Real-time Visual-Inertial 6D Object Pose Tracking 文章概括摘要I. INTRODACTIONII. 相关工作III. APPROACHA. 姿态跟踪工作流程B. VIPose网络 文章概括 引用: inproceedings{ge2021vipose,title{Vipose: Real-time visual-inertial 6d object pose tra…...

微服务治理详解
文章目录 什么是微服务架构为什么要使用微服务单体架构如何转向微服务架构服务治理服务治理治的是什么服务注册与发现服务熔断降级服务网关服务调用服务负载均衡服务配置中心 微服务解决方案SpringCloud体系EurekaHystrixGatewayOpenFeignRibbonConfig SpringCloud Alibaba体系…...

“南海明珠”-黄岩岛(民主礁)领海基线WebGIS绘制实战
目录 前言 一、关于岛屿的基点位置 1、领海基点 二、基点坐标的转换 1、最底层的左边转换 2、单个经纬度坐标点转换 3、完整的转换 三、基于天地图进行WebGIS展示 1、领海基点的可视化 2、重要城市距离计算 四、总结 前言 南海明珠黄岩岛,这座位于南海的…...
Oracle数据库 创建dblink的过程及其用法详解
前言 dblink是Oracle数据库中用于连接不同数据库实例的一种机制。通过dblink,用户可以在一个数据库实例中直接查询或操作另一个数据库实例中的表、视图或存储过程。 dblink的作用主要体现在以下几个方面: 跨数据库操作:允许用户…...

Linux从0——1之shell编程4
声明! 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团队无关&a…...

pycharm快速更换虚拟环境
目录 1. 选择Conda 虚拟环境2. 创建环境3. 直接选择现有虚拟环境 1. 选择Conda 虚拟环境 2. 创建环境 3. 直接选择现有虚拟环境...
MVVM框架
MVVM由以下三个内容构成: Model:数据模型View:界面ViewModel:作为桥梁负责沟通View和Model 在JQuery时期,如果需要刷新UI,需要先取到对应的 DOM 再更新 UI,这样数据和业务的逻辑就和⻚⾯有强耦合。 在 MVVM 中,UI 是…...
数据仓库在大数据处理中的作用
数据仓库(Data Warehouse,简称DW或DWH)是一个面向主题的、集成的、相对稳定的、反映历史变化的数据集合,用于支持管理决策。以下是对数据仓库及其在大数据处理中作用的详细解释: 一、数据仓库的定义 面向主题&#x…...
前端Javascript、Vue、CSS等场景面试题目(二)
前端面试场景题目(一)-CSDN博客 针对您提供的前端场景面试题目,以下是详细的回答: 1. 如何通过 CSS 实现美观的自定义复选框和单选按钮? 方法:使用 CSS 伪元素 ::before 和 ::after,以及隐藏…...
鸿蒙学习生态应用开发能力全景图-开发者支持平台(5)
鸿蒙相关平台作用: 开发者社区:开发者技术交流平台,帮助开发者探索开发实践、交流心得经验、获悉业界动态、答疑解惑。 开发者学堂:聚合官方鸿蒙生态课程,课程有慕课、微课、直播课、训练营等多种形式ÿ…...

计算机网络各层设备总结归纳(更新ing)
计算机网络按照OSI(开放式系统互联)模型分为七层,每一层都有其特定的功能和对应的网络设备。以下是各层对应的设备: 1. 物理层(Physical Layer) 设备:中继器(Repeater)、集线器…...

3. Spring Cloud Eureka 服务注册与发现(超详细说明及使用)
3. Spring Cloud Eureka 服务注册与发现(超详细说明及使用) 文章目录 3. Spring Cloud Eureka 服务注册与发现(超详细说明及使用)前言1. Spring Cloud Eureka 的概述1.1 服务治理概述1.2 服务注册与发现 2. 实践:创建单机 Eureka Server 注册中心2.1 需求说明 图解…...

品牌如何利用大数据工具,进行消费者洞察分析?
存量竞争的时代, 消费者聆听是品牌持续增长的关键,借助大数据的消费者数据洞察,可以帮助品牌分析消费者的所思所想及行为特征,获取消费者对产品的需求痛点、使用感受,对品牌的评价口碑等,从而帮助品牌更好地…...
鸿蒙实现 web 传值
前言:安卓和 IOS 加载 H5 的时候,都有传值给到 H5 或者接收 H5 值,鸿蒙也可传值和接收 H5 的内容,以下是鸿蒙传值给 H5 端的具体操作 一: 定义好 H5 和鸿蒙传值的方法名,两端必须保持方法名一致 // xxx.ets import …...

uniapp vuex的使用
实现组件全局(数据)管理的一种机制,可以方便的实现组件之间共享数据,不同于上述三种传递值的方式。 可以把vuex当成一个store仓库,可以集中管理共享的数据,并且存储在vuex中的数据都是响应式的,…...

RabbitMQ实战启程:从原理到部署的全方位探索(上)
文章目录 一、RabbitMQ简介1.1、概述1.2、特性 二、RabbitMQ原理架构三、RabbitMQ应用场景3.1 简单模式3.2 工作模式3.3 发布订阅3.4 路由模式3.5 主题订阅模式 四、同类中间件对比五、RabbitMQ部署5.1 单机部署5.1.1 安装erlang5.1.2 安装rabbitmq 5.2 集群部署(镜…...

【论文复现】轻松利用自适应特征融合实现去雾
📝个人主页🌹:Eternity._ 🌹🌹期待您的关注 🌹🌹 ❀ 智慧医疗 介绍创新点网络结构特征提取阶段自适应融合阶段图像重建阶段上下文增强模块CEM特征融合模块AFM 结果分析 提示 论文题目࿱…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...

centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...

免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...

ZYNQ学习记录FPGA(二)Verilog语言
一、Verilog简介 1.1 HDL(Hardware Description language) 在解释HDL之前,先来了解一下数字系统设计的流程:逻辑设计 -> 电路实现 -> 系统验证。 逻辑设计又称前端,在这个过程中就需要用到HDL,正文…...

欢乐熊大话蓝牙知识17:多连接 BLE 怎么设计服务不会乱?分层思维来救场!
多连接 BLE 怎么设计服务不会乱?分层思维来救场! 作者按: 你是不是也遇到过 BLE 多连接时,调试现场像网吧“掉线风暴”? 温度传感器连上了,心率带丢了;一边 OTA 更新,一边通知卡壳。…...
6.9本日总结
一、英语 复习默写list11list18,订正07年第3篇阅读 二、数学 学习线代第一讲,写15讲课后题 三、408 学习计组第二章,写计组习题 四、总结 明天结束线代第一章和计组第二章 五、明日计划 英语:复习l默写sit12list17&#…...

Linux入门课的思维导图
耗时两周,终于把慕课网上的Linux的基础入门课实操、总结完了! 第一次以Blog的形式做学习记录,过程很有意思,但也很耗时。 课程时长5h,涉及到很多专有名词,要去逐个查找,以前接触过的概念因为时…...

【图片转AR场景】Tripo + Blender + Kivicube 实现图片转 AR 建模
总览 1.将 2D 图片转为立体建模 2. 3. 一、将 2D 图片转为立体建模 1.工具介绍 Tripo 网站 2.找图片 找的图片必须是看起来能够让 AI 有能力识别和推理的,因为现在的AI虽然可以补全但是能力还没有像人的想象力那么丰富。 比如上面这张图片,看起来虽…...