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

news2025/2/28 4:12:15

目录

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

实例036 使窗体标题栏文字右对齐

实例说明 窗口标题栏中的文字是窗口的重要说明&#xff0c;该文字可以标示窗口的功能、状态或名称等信息&#xff0c;一般该文字是居左显示的&#xff0c;在本例中设计一个标题栏文字右对齐的窗口。本实例运行结果如图1.36所示。 技术要点 在C# 2.0中实现这一功能非常容易&am…

【LeetCode】45. 跳跃游戏 II - 贪婪算法

目录标题 2023-8-11 09:49:25 45. 跳跃游戏 II 2023-8-11 09:49:25 自己没做出来&#xff0c;废物Orz class Solution {public int jump(int[] nums) {int length nums.length;int end 0;int maxPosition 0;int steps 0;for (int i 0; i < length - 1; i) {maxPosit…

Maven在IDEA2021版本中全局配置(一次配置处处生效)

前言 我们在开发中&#xff0c;Maven是必不可少的&#xff0c;但是每次都需要设置一遍Maven的仓库和settings.xml。真的是心累&#xff0c;今天教大家全局配置一下。再也不要每次项目都配了&#xff0c;Maven还经常出问题。 解决方案 友情提示&#xff1a;小编的IDEA版本为2…

前沿分享-你好,我的括约肌

通过智能主动植入物彻底改变严重压力性尿失禁的治疗&#xff0c;是利用嵌入式系统和微技术领域的最新技术的解决方案。 由 肌机电系统&#xff08;MEMS&#xff09; 驱动&#xff0c;放置在尿道周围&#xff0c;旨在根据患者的活动自动控制&#xff0c;无需手动调整。 当患者从…

Streamlit 入门教程:构建一个Dashboard

Streamlit 是一个用于创建数据科学和机器学习应用程序的开源 Python 库。它的主要目标是使开发人员能够以简单的方式快速构建交互式的数据应用&#xff0c;而无需过多的前端开发经验。Streamlit 提供了一种简单的方法来转换数据脚本或分析代码为具有可视化界面的应用程序&#…

【Tool】win to go 制作随身硬盘

前言 话说我一冲动买了512G固态硬盘&#xff0c;原本是装个ubuntu系统的&#xff0c;这个好装&#xff0c;但是用处太少&#xff0c;就像改成win10的 经历一堆坑之后&#xff0c;终于使用WTG安装好了 步骤 1.下载个WTG辅助工具 Windows To Go 辅助工具|WTG辅助工具 v5.6.1…

【HCIP】BGP基础建邻和宣告实验

题目&#xff1a; 拓扑图&#xff1a; 配置 R1 //配置IP及环回 [r1]int l0 [r1-LoopBack0]ip add 1.1.1.1 24 [r1-LoopBack0]int g0/0/0 [r1-GigabitEthernet0/0/0]int g0/0/1 [r1-GigabitEthernet0/0/1]ip add 13.1.1.1 24 [r1-GigabitEthernet0/0/1]q //建立BGP [r1]bgp 1 […

.NET对象的内存布局

在.NET中&#xff0c;理解对象的内存布局是非常重要的&#xff0c;这将帮助我们更好地理解.NET的运行机制和优化代码&#xff0c;本文将介绍.NET中的对象内存布局。 .NET中的数据类型主要分为两类&#xff0c;值类型和引用类型。值类型包括了基本类型(如int、bool、double、cha…

【分布式技术专题】「分布式技术架构」手把手教你如何开发一个属于自己的事件总线EventBus服务功能

手把手教你如何开发一个属于自己的事件总线EventBus服务功能 事件总线 — EventBusEventBus的基本原理 总体架构图定义事件监听器EventListener接口方法 — topic方法 — onMessage 定义事件驱动传输模型定义事件监听器EventListenerRegistry接口initRegistryEventListener注册…

Oracle 知识篇+会话级全局临时表在不同连接模式中的表现

标签&#xff1a;会话级临时表、全局临时表、幻读释义&#xff1a;Oracle 全局临时表又叫GTT ★ 结论 ✔ 专用服务器模式&#xff1a;不同应用会话只能访问自己的数据 ✔ 共享服务器模式&#xff1a;不同应用会话只能访问自己的数据 ✔ 数据库驻留连接池模式&#xff1a;不同应…

风口来临,你真的了解什么是嵌入式吗?

什么是嵌入式&#xff1f; 书本上的定义是这样的&#xff1a; 嵌入式&#xff08;Embedded&#xff09;是指将计算机系统嵌入到被控制对象中的一种技术。它不同于传统的个人电脑或服务器&#xff0c;而是专门设计用来执行特定功能的计算机系统。嵌入式系统通常被用于控制、监测…

【1289. 下降路径最小和 II】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 给你一个 n x n 整数矩阵 grid &#xff0c;请你返回 非零偏移下降路径 数字和的最小值。 非零偏移下降路径 定义为&#xff1a;从 grid 数组中的每一行选择一个数字&#xff0c;且按顺序选出来的数…

odoo 开发入门教程系列-模块交互

模块交互 在上一章中&#xff0c;我们使用继承来修改模块的行为。在我们的房地产场景中&#xff0c;我们希望更进一步&#xff0c;能够为客户生成发票。Odoo提供了一个开发票模块&#xff0c;因此直接从我们的房地产模块创建发票是很简单的&#xff0c;也就是说&#xff0c;一…

比较 Java 中的 ModelMapper 和 MapStruct:自动映射器的强大功能

了解如何在自动映射器 ModelMapper 和 MapStruct 之间进行选择&#xff0c;以提高生产力和可维护性&#xff0c;并减少数据映射中的错误。 在 Java 应用程序中&#xff0c; 数据映射 是一项常见任务&#xff0c;涉及将对象从一种类型转换为另一种类型。这个过程可能会变得复杂而…

浅谈Spring与字节码生成技术

概要 今天来谈一谈我们熟知的Spring框架和字节码技术有什么联系。 Java程序员几乎都了解Spring。 它的IoC&#xff08;依赖反转&#xff09;和AOP&#xff08;面向切面编程&#xff09;功能非常强大、易用。而它背后的字节码生成技术&#xff08;在运行时&#xff0c;根据需要…

Linu学习笔记——常用命令

Linux 常用命令全拼&#xff1a; Linux 常用命令全拼 | 菜鸟教程 一、切换root用户 1.给root用户设置密码 sudo passwd root 2.输入密码&#xff0c;并确认密码 3.切换到root用户 su&#xff1a;Swith user(切换用户) su root 二、切换目录 目录结构&#xff1a;Linux 系…

APP外包开发的H5开发框架

跨平台移动应用开发框架允许开发者使用一套代码在多个操作系统上构建应用程序&#xff0c;从而节省时间和资源。以下是一些常见的跨平台移动应用开发框架以及它们的特点&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0…

再论态势感知中的几个问题

1、态势中的状态信息与趋势信息有何不同 在分析和决策过程中&#xff0c;态势是指当前的情境、环境或状况。状态信息和趋势信息是对态势的不同方面进行描述和分析的方式。 状态信息是关于当前态势的实时或静态描述。它提供的是当前的数据、指标或状态的具体数值或描述。例如&am…

使用python-magic和wxPython识别文档类型

以下是一篇关于使用python-magic模块和wxPython库识别文档类型的相关博客文章的示例&#xff1a; 摘要&#xff1a; 本文介绍了如何使用python-magic模块和wxPython库创建一个简单的文件列表应用程序&#xff0c;该应用程序可以显示所选文件夹中文件的类型。 介绍&#xff1…