软件设计模式系列之五——建造者模式

news2024/12/22 19:56:43

1 模式的定义

建造者模式是一种对象创建型设计模式,它将一个复杂对象的构建过程与其表示分离。这意味着你可以使用相同的构建过程来创建不同类型的对象,而不必关心每个对象的内部细节。这种模式适用于构建具有复杂配置的对象,例如具有多个可选组件的汽车。

2 结构

建造者模式的结构包括以下几个关键部分:
在这里插入图片描述

Director(指导者):负责指导构建过程的顺序,它并不直接创建产品,而是通过建造者来构建产品。
Builder(建造者):定义了创建产品各个部分的接口,具体的建造者实现这些接口以构建具体产品。
ConcreteBuilder(具体建造者):实现了Builder接口,负责具体产品的构建过程。
Product(产品):表示最终构建出的复杂对象,它通常包含了多个部分。

3 举例说明

建造者模式可以通过组装电脑的过程来解释。在电脑组装中,你有多个可选组件(如CPU、内存、硬盘、显卡等),每个组件有不同的配置选项。建造者模式将这个过程分解为以下部分:
在这里插入图片描述

产品(Product):电脑是最终的产品,具有多个组件(CPU、内存等)。

抽象建造者(Builder):定义了创建电脑各个组件的接口,例如安装CPU、内存等。

具体建造者(Concrete Builder):每个具体建造者实现了抽象建造者接口,负责构建不同配置的电脑,例如高性能电脑、办公电脑等。

指导者(Director):负责指导建造电脑的顺序,如安装CPU、内存、硬盘等。

通过建造者模式,你可以使用相同的构建过程创建不同类型的电脑,保持了灵活性和可维护性,同时将构建过程与最终产品分离,使得电脑组装变得更加可控和可扩展。

4 实现步骤

建造者模式的实现步骤通常包括:
在这里插入图片描述

定义产品的抽象类或接口,以及产品的各个部分。
创建具体建造者类,实现Builder接口,负责构建产品的各个部分。
创建Director类,负责指导建造过程的顺序,它包含一个Builder成员变量用于构建产品。
在客户端代码中,创建Director对象并指定一个具体的建造者对象,然后通过Director来构建产品。

5 代码实现

以下是一个简单的Java代码示例,演示了如何使用建造者模式来组装电脑,包括CPU、硬盘和主板等组件.

// 产品类:电脑
class Computer {
    private String cpu;
    private String hardDisk;
    private String motherboard;

    public void setCPU(String cpu) {
        this.cpu = cpu;
    }

    public void setHardDisk(String hardDisk) {
        this.hardDisk = hardDisk;
    }

    public void setMotherboard(String motherboard) {
        this.motherboard = motherboard;
    }

    @Override
    public String toString() {
        return "Computer [CPU=" + cpu + ", HardDisk=" + hardDisk + ", Motherboard=" + motherboard + "]";
    }
}

// 抽象建造者接口
interface ComputerBuilder {
    void buildCPU();

    void buildHardDisk();

    void buildMotherboard();

    Computer getComputer();
}

// 具体建造者类
class HighEndComputerBuilder implements ComputerBuilder {
    private Computer computer;

    public HighEndComputerBuilder() {
        computer = new Computer();
    }

    @Override
    public void buildCPU() {
        computer.setCPU("High-end CPU");
    }

    @Override
    public void buildHardDisk() {
        computer.setHardDisk("1TB SSD");
    }

    @Override
    public void buildMotherboard() {
        computer.setMotherboard("High-end Motherboard");
    }

    @Override
    public Computer getComputer() {
        return computer;
    }
}

// 指导者类
class Director {
    private ComputerBuilder computerBuilder;

    public Director(ComputerBuilder builder) {
        this.computerBuilder = builder;
    }

    public void constructComputer() {
        computerBuilder.buildCPU();
        computerBuilder.buildHardDisk();
        computerBuilder.buildMotherboard();
    }
}

// 客户端代码
public class Main {
    public static void main(String[] args) {
        ComputerBuilder builder = new HighEndComputerBuilder();
        Director director = new Director(builder);

        director.constructComputer();
        Computer highEndComputer = builder.getComputer();

        System.out.println("High-end Computer Specs:");
        System.out.println(highEndComputer);
    }
}

在这个示例中,我们定义了产品类Computer,抽象建造者接口ComputerBuilder,以及具体建造者类HighEndComputerBuilder。指导者类Director负责控制构建过程的顺序。客户端代码创建具体建造者对象并使用指导者来构建电脑。这样,我们就可以轻松地创建不同配置的电脑对象。

6 典型应用场景

建造者模式在创建复杂对象时,它可以提供一种更加灵活和可维护的方式。以下是建造者模式的一些典型应用场景:

创建复杂对象:建造者模式适用于构建复杂的对象,这些对象可能有多个组件或部分,而且这些组件之间存在复杂的依赖关系。例如,创建包含多个可选组件的电子产品、汽车、飞机等。

隐藏构造过程的细节:建造者模式允许将构造对象的复杂性封装在具体建造者中,客户端代码只需关心如何指导建造过程,而不必关心对象的具体构建细节。这有助于降低客户端代码的复杂性。

创建不同配置的对象:如果需要创建多个具有相似属性但不同配置的对象,建造者模式非常有用。你可以使用不同的具体建造者来创建不同配置的对象,而不必重复相似的构建代码。

提高代码可读性:通过使用建造者模式,可以清晰地看到对象的构建过程,使代码更易于理解和维护。每个具体建造者都负责一部分构建过程,使代码更加模块化和可读性更高。

避免对象不完整或不一致:建造者模式可以确保在构建对象的过程中不会产生不完整或不一致的对象。在构建过程中,要么对象完全构建成功,要么不构建。

总之,建造者模式在需要创建复杂对象、隐藏构建细节、提高可读性和灵活性等情况下非常有用。它允许你以分步骤的方式构建对象,并在创建过程中动态配置对象的属性,使得代码更易于管理和维护。

7 优缺点

优点:

将构建过程与产品表示分离,使得构建过程更灵活。
可以通过不同的具体建造者来创建不同类型的对象。
可以重复使用相同的构建过程来构建不同的对象。

缺点:

增加了代码的复杂性,因为需要定义抽象建造者和具体建造者类。
如果产品的部分组件较少,可能会显得过于繁琐。

8 类似模式

建造者模式与以下几种设计模式有一定的相似性:

抽象工厂模式(Abstract Factory Pattern):抽象工厂模式也用于创建复杂对象,但它关注的是创建一组相关或相互依赖的对象,而不是单个对象。建造者模式关注的是构建单个复杂对象,其构建过程逐步进行。

工厂模式(Factory Pattern):工厂模式用于创建对象,但不像建造者模式那样关心对象的构建过程的细节。工厂模式简单地返回一个已经构建好的对象,而建造者模式允许在构建过程中设置对象的属性和配置。

原型模式(Prototype Pattern):原型模式通过复制现有对象来创建新对象,而不需要详细的构建过程。与建造者模式不同,原型模式不涉及构建对象的复杂性,而是复制现有对象的状态。

9 小结

建造者模式是一种有助于创建复杂对象的设计模式,它通过将构建过程分步骤进行,允许你创建不同类型的对象,并保持构建过程的独立性。通过定义抽象建造者和具体建造者类,以及使用指导者来管理构建顺序,你可以更好地控制对象的构建过程。建造者模式在需要创建多个不同配置的对象或构建过程较为复杂的情况下特别有用。但要注意,它可能会增加代码的复杂性,因此应在合适的情况下使用。

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

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

相关文章

查看selenium具体版本的方法

1、 查看自己selenium版本 方法一: 本机进入CMD 在cmd窗口中输入 pip show selenium如果是在Pycharm中直接安装的selenium。则有可能会有如下提示。那么请尝试方法二。 方法二: 在pycharm中查看selenium版本 步骤一:在pycharm里打开命…

SpringMVC系列(五)之JSR303和拦截器

目录 一. JSR303 1.1 JSR303是什么 1.2 为什么要使用JSR303 1.3 JSR303常用注解 1.4 JSR303快速入门 1. 导入相关pom依赖 2. 配置校验规则 3. 入门示例 二. SpringMVC的拦截器 2.1 什么是拦截器 2.2 拦截器与过滤器的区别 2.3 拦截器工作原理 2.4 入门示例 1. 创建…

Gin路由中间件详解

什么是中间件 Gin 中的中间件必须是一个 gin.HandlerFunc 类型,配置路由的时候可以传递多个 func 回调函 数, 最后一个 func 回调函数前面触发的方法 都可以称为中间件。 中间件操作演示 方法一: 直接写在func,回调函数内 r.GET("/middle",func(ctx *gin.Cont…

Pytorch中张量矩阵乘法函数(mm, bmm, matmul)使用说明,含高维张量实例及运行结果

Pytorch中张量矩阵乘法函数使用说明 1 torch.mm() 函数1.1 torch.mm() 函数定义及参数1.2 torch.bmm() 官方示例 2 torch.bmm() 函数2.1 torch.bmm() 函数定义及参数2.2 torch.bmm() 官方示例 3 torch.matmul() 函数3.1 torch.matmul() 函数定义及参数3.2 torch.matmul() 规则约…

黑马头条 热点文章实时计算、kafkaStream

热点文章-实时计算 1 今日内容 1.1 定时计算与实时计算 1.2 今日内容 kafkaStream 什么是流式计算kafkaStream概述kafkaStream入门案例Springboot集成kafkaStream 实时计算 用户行为发送消息kafkaStream聚合处理消息更新文章行为数量替换热点文章数据 2 实时流式计算 2…

【C++】哈希思想的应用——位图、布隆过滤器和哈希切割

前言: 前面我们学习了unordered_map和unordered_set和哈希表哈希桶等,并且我们自己用哈希桶封装了unordered_map和unordered_set。我们知道哈希的查找效率非常高为O(1),本章我们将延续哈希的思想,共同学习哈希的应用。 目录 &am…

sh脚本工具集锦(文件批量操作、音视频相关)持续更新

1 文件夹目录下所有图片转换成视频文件 pic_2_videos.sh: #!/bin/bash # 放到图片文件夹目录下,把所有jpeg图片推成视频文件 # sh pic_2_videos.sh 0 # 0: pad to 1920*1080 ; 1 or other no pad pad_1920$1if [[ $pad_1920 0 ]] thenfilesls|grep jp…

【Flink】 FlinkCDC读取Mysql( DataStream 方式)(带完整源码,直接可使用)

简介: FlinkCDC读取Mysql数据源,程序中使用了自定义反序列化器,完整的Flink结构,开箱即用。 本工程提供 1、项目源码及详细注释,简单修改即可用在实际生产代码 2、成功编译截图 3、自己编译过程中可能出现的问题 4、mysql建表语句及测试数据 5、修复FlinkCDC读取Mys…

【C++】匿名对象 ① ( 匿名对象引入 | 匿名对象简介 | 匿名对象概念 | 匿名对象作用域 - 对象创建与销毁 )

文章目录 一、匿名对象引入二、匿名对象简介1、匿名对象概念2、匿名对象作用域 - 对象创建与销毁3、代码示例 - 创建并使用匿名对象 一、匿名对象引入 匿名对象引入 : 在上一篇博客 【C】拷贝构造函数调用时机 ② ( 对象值作为函数参数 | 对象值作为函数返回值 ) 中 , 讲到了 如…

【Java基础】- RMI原理和使用详解

【Java基础】- RMI原理和使用详解 文章目录 【Java基础】- RMI原理和使用详解一、什么RMI二、RMI原理2.1 工作原理图2.2 工作原理 三、RMI远程调用步骤3.1 RMI远程调用运行流程图3.2 RMI 远程调用步骤 四、JAVA RMI简单实现4.1 如何实现一个RMI程序4.2 JAVA实现RMI程序 一、什么…

小程序中如何查看指定会员的所有订单?

在小程序中,查看指定会员的所有订单可以通过如下方式实现。 1. 找到指定的会员卡。在管理员后台->会员管理处,找到需要查看订单记录的会员卡。也支持对会员卡按卡号、手机号和等级进行搜索。 2. 查看会员卡详情。点击查看详情进入该会员卡的详情页面…

GTS 中testPersistentProcessMemory fail 详解

0. 前言 GTS 在测试 case armeabi-v7a GtsMemoryTestCases 的时候出现下面异常,本文总结一下。 com.google.android.memory.gts.MemoryTest#testPersistentProcessMemory 1. error log 09-14 09:41:40.523 10182 13340 13359 E TestRunner: failed: testPersiste…

网攻西北工业大学的美国安局人员真实身份锁定!

14日,《环球时报》从国家计算机病毒应急处理中心和360获悉,在侦办西北工业大学网络攻击案过程中,我方成功提取了名为“二次约会”(Second Date)“间谍”软件的多个样本。在多国业内伙伴通力合作下,现已成功…

【ELK】日志分析系统概述及部署

目录 一、ELK概述 1、ELK是什么? 2、ELK的组成部分 2.1 ElasticSearch (1)分片和副本 (2)es和传统数据库的区别 2.2 Kiabana 2.3 Logstash (1)Log Stash主要组件 2.4 可添加的其它组件 …

Opencv之区域生长和分裂

区域生长 1.基本原理 区域生长法是较为基础的一种区域分割方法 它的基本思想我说的通俗些,即是一开始有一个生长点(可以一个像素也可以是一个小区域),从这个生长点开始往外扩充,扩充的意思就是它会把跟自己有相似特征…

Python工程师Java之路(p)Maven聚合和继承

文章目录 依赖管理依赖传递可选依赖和排除依赖 继承与聚合 依赖管理 指当前项目运行所需的jar&#xff0c;一个项目可以设置多个依赖 <!-- 设置当前项目所依赖的所有jar --> <dependencies><!-- 设置具体的依赖 --><dependency><!-- 依赖所属群组…

gmssl v2 用 dgst 命令通过 sm2 签名出的结果,在别的工具上无法验签的问题分析

结论 通过分析发现&#xff0c;导致问题的原因是&#xff1a;gmssl v2 调用的算法不是 sm2 算法。 分析详情 具体情况如下所述 在 gmssl 调用 pkey_ec_init 函数时&#xff0c;默认会把 ec_scheme 设置为 NID_secg_scheme 签名的过程中会调用 pkey_ec_sign 函数&#xff0c…

【Redis】Redis的特性和应用场景 · 数据类型 · 持久化 · 数据淘汰 · 事务 · 多机部署

【Redis】Redis常见面试题&#xff08;3&#xff09; 文章目录 【Redis】Redis常见面试题&#xff08;3&#xff09;1. 特性&应用场景1.1 Redis能实现什么功能1.2 Redis支持分布式的原理1.3 为什么Redis这么快1.4 Redis实现分布式锁1.5 Redis作为缓存 2. 数据类型2.1 Redis…

Day_14 > 指针进阶(3)> bubble函数

目录 1.回顾回调函数 2.写一个bubble_sort函数 2.1认识一下qsort函数 ​编辑2.2写bubble_sort函数 今天我们继续深入学习指针 1.回顾回调函数 我们回顾一下之前学过的回调函数 回调函数就是一个通过函数指针调用的函数 如果你把函数的指针&#xff08;地址&#xff09;…

​Qt for Python 入门¶​

本页重点介绍如何从源代码构建Qt for Python&#xff0c;如果你只想安装PySide2。 与你需要运行&#xff1a;pip pip install pyside2有关更多详细信息&#xff0c;请参阅我们的快速入门指南。此外&#xff0c;您可以 查看与项目相关的常见问题解答。 一般要求 Python&#xf…