(一)创建型设计模式:3、建造者模式(Builder Pattern)

目录

1、建造者模式含义

2、建造者模式的讲解

3、使用C++实现建造者模式的实例

4、建造者模式的优缺点

5、建造者模式VS工厂模式


1、建造者模式含义

The intent of the Builder design pattern is to separate the construction of a complex object from its representation. By doing so the same construction process can create different representations.

将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。

其实上面这句话本身是有点晦涩难懂,后面在网上看到有人这样说,便留下深刻的印象:

当一个类的构造函数参数个数超过4个,而且这些参数有些是可选的参数,考虑使用构造者模式。

这个解释也可以理解为应用场景,当我们单纯懂得设计模式怎么实现并不重要,重要的是要知道适用于什么场景,这个就得靠一些经验和思考了。

2、建造者模式的讲解

从上面的UML可以看出,建造者模式涉及到以下四个角色的概念:

(1)抽象建造者角色:提供一个接口,规范产品对象的建造,一般由子类实现。一般来说,产品的组成部分数与建造方法数相同,即有多少组成部分,就有多少个建造方法。

(2)具体建造者角色:该角色实现了抽象建造者抽象建造者接口,主要是实现所有声明的方法以及返回建造好的产品实例。

(3)导演者角色:负责调用具体建造者按照顺序建造产品。导演者只负责调度,真正执行的是具体建造者角色。

(4)产品角色:该角色是建造的复杂对象,提供基本方法。

3、使用C++实现建造者模式的实例


#include <iostream>
#include <string>

// 产品类
class Product {
public:
    void setPartA(const std::string& partA) {
        m_partA = partA;
    }

    void setPartB(const std::string& partB) {
        m_partB = partB;
    }

    void setPartC(const std::string& partC) {
        m_partC = partC;
    }

    void show() const {
        std::cout << "Product Parts: " << m_partA << ", " << m_partB << ", " << m_partC << std::endl;
    }

private:
    std::string m_partA;
    std::string m_partB;
    std::string m_partC;
};

// 抽象建造者类
class Builder {
public:
    virtual void buildPartA() = 0;
    virtual void buildPartB() = 0;
    virtual void buildPartC() = 0;
    virtual Product* getResult() = 0;
};

// 具体建造者类
class ConcreteBuilder : public Builder {
public:
    void buildPartA() override {
        m_product->setPartA("Part A");
    }

    void buildPartB() override {
        m_product->setPartB("Part B");
    }

    void buildPartC() override {
        m_product->setPartC("Part C");
    }

    Product* getResult() override {
        return m_product;
    }

private:
    Product* m_product = new Product();
};

// 指挥者类
class Director {
public:
    void construct(Builder* builder) {
        builder->buildPartA();
        builder->buildPartB();
        builder->buildPartC();
    }
};

int main() {
    Director director;
    ConcreteBuilder builder;

    director.construct(&builder);
    Product* product = builder.getResult();
    product->show();

    delete product;

    return 0;
}

在上述示例中,我们定义了一个产品类(Product),它有三个部分(Part A、Part B、Part C)。然后,我们定义了一个抽象建造者类(Builder),其中包含了构建产品各个部分的纯虚函数。接着,我们实现了具体的建造者类(ConcreteBuilder),它实现了抽象建造者类的纯虚函数,并负责构建产品对象。最后,我们定义了一个指挥者类(Director),它负责调用建造者的方法来构建产品。

在主函数中,我们创建了一个具体的建造者对象,并将其传递给指挥者对象。指挥者根据具体的建造者对象来构建产品,最终得到一个完整的产品对象。我们可以通过产品对象的show()方法来展示产品的各个部分。

这就是一个简单的建造者模式的C++源码示例

4、建造者模式的优缺点

(1)优点:

1)分离构建过程和表示:建造者模式可以将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示形式。这样可以提高代码的灵活性和可维护性。

2)更好的封装性:通过建造者模式,可以将对象的构建过程封装在具体的建造者类中,客户端只需要与指挥者进行交互,无需关心具体的构建细节。这样可以隐藏对象的创建过程,提供更好的封装性。

3)可以控制构建过程:建造者模式允许你逐步构建对象,并在每个步骤中进行必要的操作、检查或验证。这样可以更加灵活地控制对象的构建过程,满足不同的需求。

4)创建不同表示形式的对象:通过定义不同的建造者和指挥者,可以根据需求定制不同的构建过程,创建不同的产品表示形式。这样可以提供更多的选择和灵活性。

(2)缺点:

1)增加了代码量:使用建造者模式会增加额外的类和接口,从而增加了代码量。如果对象的构建过程比较简单,使用建造者模式可能会显得过于繁琐。

2)增加了系统复杂性:引入建造者模式会增加系统的复杂性,因为需要定义多个类和接口,并且需要协调指挥者和建造者之间的关系。这可能会增加理解和维护的难度。

3)不适用于创建简单对象:如果对象的构建过程比较简单,只有少量的步骤或参数,使用建造者模式可能会显得过于繁琐。此时,直接使用简单工厂或工厂方法模式可能更加合适。

总的来说,建造者模式通过分离构建过程和表示,提供了更好的封装性和灵活性,可以控制构建过程并创建不同表示形式的对象。然而,它也增加了代码量和系统复杂性,不适用于创建简单对象。

5、建造者模式VS工厂模式

建造者模式和工厂模式是两种常见的创建型设计模式,它们有以下几点区别:

(1)目的不同:工厂模式关注的是创建对象的过程,将对象的创建逻辑封装在一个工厂类中,通过工厂类来创建具体的对象。而建造者模式关注的是创建复杂对象的过程,将对象的构建过程与其表示分离,通过指挥者和建造者来逐步构建对象。

(2)对象复杂度不同:工厂模式适用于创建简单对象,通常只需要一两个步骤即可完成对象的创建。而建造者模式适用于创建复杂对象,对象的构建过程需要多个步骤,并且可以根据需求定制不同的构建过程。

(3)调用方式不同:工厂模式通过调用工厂类的方法来创建对象,客户端直接与工厂类交互。而建造者模式通过指挥者来控制建造者的构建过程,客户端只需要与指挥者进行交互,无需直接与建造者类交互。

(4)灵活性不同:工厂模式相对较为灵活,可以根据需要扩展和添加新的产品类型,只需要添加对应的具体产品和工厂类即可。而建造者模式相对更加灵活,可以根据需要定制不同的构建过程,创建不同的产品表示形式。

总的来说,工厂模式适用于创建简单对象,将对象的创建过程封装在工厂类中;而建造者模式适用于创建复杂对象,通过指挥者和建造者来分步构建对象。
 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue自定义指令动态绑定

在企业微信侧边栏应用中&#xff0c;给dialog添加了拖拽功能&#xff0c;但是因为dialog高度超过了页面高度&#xff0c;所以高度100%时拖拽有个bug--自动贴到窗口顶部而且企业侧边栏宽高都有限制&#xff0c;拖拽效果并不理想&#xff0c;所以就想缩小dialog再进行拖拽。 拖拽…

【生成式AI】ProlificDreamer论文阅读

ProlificDreamer 论文阅读 Project指路&#xff1a;https://ml.cs.tsinghua.edu.cn/prolificdreamer/ 论文简介&#xff1a;截止2023/8/10&#xff0c;text-to-3D的baseline SOTA&#xff0c;提出了VSD优化方法 前置芝士:text-to-3D任务简介 text-to-3D Problem text-to-3D…

uniapp+vue3项目中使用vant-weapp

创建项目 通过vue-cli命令行创建项目 Vue3/Vite版要求 node 版本^14.18.0 || >16.0.0 uni-app官网 (dcloud.net.cn) npx degit dcloudio/uni-preset-vue#vite my-vue3-project打开项目 点击顶部菜单栏终端/新建终端 执行安装依赖指令 yarn install 或 npm install 安装vant…

Rust语法:变量,函数,控制流,struct

文章目录 变量可变与不可变变量变量与常量变量的Shadowing标量类型整数 复合类型 函数控制流if elseloop & whilefor in structstruct的定义Tuple Structstruct的方法与函数 变量 可变与不可变变量 Rust中使用let来声明变量&#xff0c;但是let声明的是不可变变量&#x…

windows常用shell命令大全

简介 基于鼠标操作的后果就是OS界面外观发生改变&#xff0c; 就得多花学习成本。更主要的是基于界面引导Path与命令行直达速度是难以比拟的。另外Geek很大一部分是键盘控&#xff0c;而非鼠标流的。 整理Windows的常用Shell命令&#xff0c;一方面帮助深入学习Mysql&#xf…

2023.08.13 学习周报

文章目录 摘要文献阅读1.题目2.要点3.问题4.解决方案5.本文贡献6.方法6.1 特征选择6.2 时间序列平稳性检测与数据分解6.3 基于GRU神经网络的PM2.5浓度预测 7.实验7.1 网络参数7.2 实验结果7.3 对比实验 8.讨论9.结论10.展望 PINNS模型1.自动微分2.全连接神经网络3.PINNs模型的P…

谈一谈在两个商业项目中使用MVI架构后的感悟

作者&#xff1a;leobertlan 前言 当时项目采用MVP分层设计&#xff0c;组员的代码风格差异也较大&#xff0c;代码中类职责赋予与封装风格各成一套&#xff0c;随着业务急速膨胀&#xff0c;代码越发混乱。试图用 MVI架构 单向流 形成 掣肘 带来一致风格。 但这种做法不够以…

【笔试题心得】关于KMP在笔试中的题型

好几家都考到KMP了 问的比较多的是 next数组 &#xff0c; 其实KMP的相关机制我在代码随想录算法训练营第九天|KMP算法_菜鸟的Zoom之旅的博客-CSDN博客中写道过&#xff0c;现在在复习一下&#xff0c;由于next数组的定义其实会有所歧义&#xff08;有些程序中会直接将前缀表作…

3.1 Qt样式选择器

本期内容 3.1 样式选择器 3.1.1 Universal Selector (通用选择器) 3.1.2 Type Selector (类型选择器) 3.1.3 Property Selector (属性选择器) 3.1.4 Class Selector (类选择器) 3.1.5 ID Selector (ID选择器) 3.1.6 Descendant Selector (后裔选择器) 3.1.7 Chil…

考研408 | 【计算机网络】 网络层

导图 网络层&#xff1a; 路由器功能&#xff1a;转发&路由选择 数据平面 数据平面执行的主要功能是根据转发表进行转发&#xff0c;这是路由器的本地动作。 控制平面 1.传统方法/每路由器法&#xff1a; 2.SDN方法&#xff08;Software-Defined Networking) 控制平面中的…

docker nginx ssl设置

使用docker运行nginx&#xff0c;配置代理&#xff0c;和ssl设置&#xff0c;进行https访问 一 准备 本次在centos环境中 1.已安装docker&#xff0c;docker-compose 2.运行了一个后端服务容器&#xff0c;提供基本的接口访问【可选】 3.一个域名&#xff08;已经解析到服…

mfc140u.dll丢失的解决方法-mfc140u.dll是什么文件

在使用计算机过程中&#xff0c;我们经常会遇到各种错误提示和问题&#xff0c;其中一个常见的问题是与mfc140u.dll文件有关的错误。mfc140u.dll是Microsoft Foundation Classes(MFC)的一个动态链接库文件&#xff0c;它提供了许多用于开发Windows应用程序的函数和类。 当mfc1…

go语言的database/sql结合squirrel工具sql生成器完成数据库操作

database/sql database/sql是go语言内置数据库引擎&#xff0c;使用sql查询数据库&#xff0c;配置datasource后使用其数据库操作方法对数据库操作&#xff0c;如下&#xff1a; package mainimport ("database/sql""fmt"_ "github.com/Masterminds…

回归预测 | MATLAB实现基于SAE堆叠自编辑器多输入单输出回归预测

回归预测 | MATLAB实现基于SAE堆叠自编辑器多输入单输出回归预测 目录 回归预测 | MATLAB实现基于SAE堆叠自编辑器多输入单输出回归预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 1.MATLAB实现基于SAE堆叠自编辑器多输入单输出回归预测&#xff1b; 2.运行环…

嵌入式:ARM Day1

1. 思维导图 2.作业一 3.作业2

MySQL入门学习教程(二)

上一篇文章讲的是mysql的基本操作&#xff0c;这一篇会有一点难以理解&#xff0c;本节主要内容mysql视图&#xff0c;存储过程&#xff0c;函数&#xff0c;事务&#xff0c;触发器&#xff0c;以及动态执行sql 视图view 视图是一个虚拟表&#xff0c;其内容由查询定义。同真…

day24-106.从中序与后序遍历序列构造二叉树

106.从中序与后序遍历序列构造二叉树 力扣题目链接(opens new window) 根据一棵树的中序遍历与后序遍历构造二叉树。 注意: 你可以假设树中没有重复的元素。 例如&#xff0c;给出 中序遍历 inorder [9,3,15,20,7]后序遍历 postorder [9,15,7,20,3] 返回如下的二叉树&am…

一百五十二、Kettle——Kettle9.3.0本地连接Hive3.1.2(踩坑,亲测有效)

一、目的 由于先前使用的kettle8.2版本在Linux上安装后&#xff0c;创建共享资源库点击connect时页面为空&#xff0c;后来采用如下方法&#xff0c;在/opt/install/data-integration/ui/menubar.xul文件里添加如下代码 <menuitem id"file-openZiyuanku" label&…

【软件工程】软件测试

软件测试的对象 软件程序文档 测试对象&#xff1a;各个阶段产生的源程序和文档。 软件测试的目的 基于不同的立场&#xff0c;对软件测试的目的存在着两种完全对立的观点。 &#xff08;1&#xff09;一种观点是通过测试暴露出软件中所包含的故障和缺陷(从用户的角度)&#xf…

汇编指令练习

1.大小比较&#xff08;循环&#xff09; start: /*mov r0,#0x9mov r1,#0xfb LoopLoop:cmp r0,r1beq stopsubhi r0,r0,r1subcc r1,r1,r0b Loop stop:b stop.end 仿真图 2. 1到100之和 start:mov r0,#0x1mov r1,#0x0b sum sum:add r1,r1,r0add r0,r0,#0x1cmp r0,#0x65beq sto…