Java设计模式:创建型模式→建造者模式

Java 建造者模式详解

1. 定义

建造者模式(Builder Pattern)是一种创建型设计模式,允许使用多个简单的对象一步步构建一个复杂的对象。该模式使用一个建造者对象来构造一个最终的对象,提供清晰的分步构建流程,从而使得产品的构建过程独立于其表示。

2. 基本思想

建造者模式的基本思想在于,针对复杂对象的构建,将对象的构建步骤与其表示分离,允许以不同的方式构建一个复杂对象。建造者模式通常是通过定义一个抽象的建造者接口,并实现多个具体的建造者来构造对象。这种模式提高了代码的可读性和可维护性,尤其是在对象构建过程复杂的情况下。

3. 基本原理

建造者模式的基本原理是:

  • 产品类(Product):需要被构造的复杂对象。
  • 建造者接口(Builder):定义了用于创建产品的抽象方法。
  • 具体建造者(ConcreteBuilder):实现建造者接口,负责具体构建产品的各个部分。
  • 指导者(Director):负责调用建造者的步骤,管理产品的构建过程。
    在这里插入图片描述

更多实用资源:

http://sj.ysok.net/jydoraemon 访问码:JYAM

4. 实现方式

4.1 基本实现

4.1.1 产品类

首先定义一个产品类,这个类包含多个属性:

public class Product {
    private String partA;
    private String partB;
    private String partC;

    public void setPartA(String partA) {
        this.partA = partA;
    }

    public void setPartB(String partB) {
        this.partB = partB;
    }

    public void setPartC(String partC) {
        this.partC = partC;
    }

    @Override
    public String toString() {
        return "Product [partA=" + partA + ", partB=" + partB + ", partC=" + partC + "]";
    }
}
4.1.2 建造者接口

定义建造者接口,规定创建产品的步骤:

public interface Builder {
    void buildPartA();
    void buildPartB();
    void buildPartC();
    Product getResult();
}
4.1.3 具体建造者

实现具体的建造者:

public class ConcreteBuilder implements Builder {
    private Product product = new Product();

    @Override
    public void buildPartA() {
        product.setPartA("Part A");
    }

    @Override
    public void buildPartB() {
        product.setPartB("Part B");
    }

    @Override
    public void buildPartC() {
        product.setPartC("Part C");
    }

    @Override
    public Product getResult() {
        return product;
    }
}
4.1.4 导演类

定义指导者类,负责管理建造过程:

public class Director {
    private Builder builder;

    public Director(Builder builder) {
        this.builder = builder;
    }

    public Product construct() {
        builder.buildPartA();
        builder.buildPartB();
        builder.buildPartC();
        return builder.getResult();
    }
}
4.1.5 客户端代码

客户端代码:

public class Client {
    public static void main(String[] args) {
        Builder builder = new ConcreteBuilder();
        Director director = new Director(builder);
        Product product = director.construct();

        System.out.println(product);
    }
}

4.2 代码分析

  • 产品类(Product):封装了多个构成部分,提供了获取最终构建结果的方法。
  • 建造者接口(Builder):定义了每个产品构建的必要步骤。
  • 具体建造者(ConcreteBuilder):具体实现了建造者接口,负责各个部分的构建。
  • 导演类(Director):协调构建过程,依赖于建造者来执行特定的步骤。

5. 工作流程

  1. 定义产品类:确定产品的结构和构成部分。
  2. 定义建造者接口:确定产品构建的步骤。
  3. 实现具体建造者:实现创建产品所需的具体步骤。
  4. 实现指导者:使用建造者接口构建产品的完整流程。
  5. 客户端使用:客户端通过导演类来客户端创建复杂对象。

6. 变种

  1. 多种建造者:通过多种具体建造者实现不同类型的产品构建,增强灵活性。
  2. 复杂建造者:如果构建步骤特别复杂,可以将构建的逻辑拆分到多个建造者和指导者中。
  3. 链式建造者:在建造者中实现链式调用,允许客户端以更流畅的方式配置产品。

7. 实际应用

建造者模式在实际应用中非常广泛,以下是一些常见的应用场景:

  1. 复杂对象创建:复杂的对象如计算机、房子等,可能包含多个部分,建造者模式可逐步构建。
  2. 数据库连接:在设置数据库连接参数时,可以使用建造者模式以分步方式构建连接对象。
  3. HTTP 请求:构建复杂的 HTTP 请求时(如 URL、头部、参数),使用建造者模式可以提高代码的可读性。

8. 使用场景

使用建造者模式的场景包括:

  • 当构造一个复杂对象的算法独立于该对象的组成部分时。
  • 当需要逐步构建一个复杂对象的各个部分,且各个部分可能在不同的上下文中有不同的组合方式。
  • 当构建对象需要多个步骤配置时,建造者模式提供了简化的方法。

9. 优缺点

优点

  1. 简化对象创建过程:通过分步构建降低了复杂度,提高了可读性。
  2. 分离对象构建与表示:构造过程与表示分离,便于修改和扩展。
  3. 增强可维护性:每个构造函数负责构造不同部分,单一职责原则,使得代码更易维护。

缺点

  1. 复杂性增加:引入多个类增加了结构复杂性,对于简单对象的创建可能显得冗余。
  2. 构建过程依赖:如果构建步骤过于复杂,会导致建造者变得庞大,难以管理。

10. 最佳实践

  1. 保证建造者易用:确保建造者能够简单直观地使用,避免复杂的构建逻辑。
  2. 适时使用导演类:在某些情况下,可能不需要导演类简化构建过程,考虑直接使用建造者。
  3. 如果有多个构建过程,可考虑使用不同的建造者:避免单个建造者类承担过多职责。

11. 注意事项

  1. 关注建造者的可读性:为建造者文档注释,保证其他开发者能理解构建流程。
  2. 控制建造者的变更:尽可能使建造者的实现遵循单一职责,以减少潜在变更影响。
  3. 监控复杂性增加:避免随意添加构建步骤,确保构建逻辑的简洁性。

12. 常见的误区

  • 认为建造者模式只适用于复杂对象:建造者模式可以应用于较简单对象构建,以提供更好的组织和结构。
  • 混淆建造者与工厂模式:建造者模式侧重于逐步构建,而工厂模式侧重于创建对象的接口。
  • 适用于所有对象构建场景:并非所有场景都适合使用建造者模式,考虑实际需求选择合适设计模式。

13. 常见问题

  • 建造者模式的关键组成部分是什么?

    • 主要由产品类、建造者接口、具体建造者和导演类组成。
  • 何时应该使用建造者模式?

    • 当对象的构建过程复杂,并且需要拆分成多个步骤时,值得考虑使用建造者模式。
  • 建造者模式和工厂模式有什么区别?

    • 工厂模式主要用于创建对象,建造者模式则用于分步构建复杂对象。

14. 总结

建造者模式是一种有助于简化复杂对象构建过程的设计模式,通过将构建步骤与对象表示分离,提升了代码的可读性、可维护性及扩展性。建造者、产品、指导者模式共同合作,使得对象创建过程既灵活又清晰。虽然在某些简单对象构建时可能显得冗余,但在构建复杂对象时用处极大,是开发过程中一种非常实用的设计模式。在使用建造者模式时,应当把握好使用场景和实现细节,以避免引入不必要的复杂性和风险。合理运用建造者模式能有效提升代码的结构性与可扩展性,是开发者值得掌握的重要设计模式之一。

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

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

相关文章

从CRUD到高级功能:EF Core在.NET Core中全面应用(三)

目录 IQueryable使用 原生SQL使用 实体状态跟踪 全局查询筛选器 并发控制使用 IQueryable使用 在EFCore中IQueryable是一个接口用于表示可查询的集合,它继承自IEnumerable但具有一些关键的区别,使得它在处理数据库查询时非常有用,普通集…

C语言之小型成绩管理系统

🌟 嗨,我是LucianaiB! 🌍 总有人间一两风,填我十万八千梦。 🚀 路漫漫其修远兮,吾将上下而求索。 C语言之小型成绩管理系统 目录 设计题目设计目的设计任务描述设计要求输入和输出要求验收要…

Linux中DataX使用第一期

简介 DataX 是阿里云 DataWorks数据集成 的开源版本,在阿里巴巴集团内被广泛使用的离线数据同步工具/平台。DataX 实现了包括 MySQL、Oracle、OceanBase、SqlServer、Postgre、HDFS、Hive、ADS、HBase、TableStore(OTS)、MaxCompute(ODPS)、Hologres、DRDS, databen…

Windows配置frp内网穿透实现远程连接

仅个人记录 本文仅介绍客户端的配置 1. 开始 frp分为服务端和客户端,为实现内网穿透需要同时配置服务端和客户端,并且版本保持一致,可以前往 frp github下载 本文使用 0.51.2 版本,从GitHub下载并解压,得到如下文件…

PHP同城配送小程序

🚀 同城极速达——您生活中的极速配送大师 📱 一款专为现代都市快节奏生活量身打造的同城配送小程序,同城极速达,集高效、便捷、智能于一身,依托ThinkPHPGatewayWorkerUniapp的强大架构,巧妙融合用户端、骑…

ESP32云开发二( http + led + lcd)

文章目录 前言先上效果图platformio.iniwokwi.tomldiagram.json源代码编译编译成功上传云端完结撒花⭐⭐⭐⭐⭐ 前言 阅读此篇前建议先看 此片熟悉下wokwi https://blog.csdn.net/qq_20330595/article/details/144289986 先上效果图 Column 1Column 2 platformio.ini wokwi…

分布式搜索引擎02

1. DSL查询文档 elasticsearch的查询依然是基于JSON风格的DSL来实现的。 1.1. DSL查询分类 Elasticsearch提供了基于JSON的DSL(Domain Specific Language)来定义查询。常见的查询类型包括: 查询所有:查询出所有数据&#xff0c…

reactor框架使用时,数据流请求流程

1. 我们在Flux打开时&#xff0c;可以看到 public abstract class Flux<T> implements CorePublisher<T> { 2. public interface CorePublisher<T> extends Publisher<T> {void subscribe(CoreSubscriber<? super T> subscriber); } Publish…

E-Prime2实现List嵌套

用E-Prime实现一个简单的List嵌套&#xff0c;实验流程基于斯特鲁程序&#xff08;色词一致/不一致实验&#xff09;。 首先File-New&#xff0c;新建一个空白项目 此时生成流程如下 Experiment Object是实验中被用到的流程或者控件对象&#xff0c;SessionProc是总流程&#x…

web-view环境下,H5页面打开其他小程序

在Web-view环境下&#xff0c;H5页面无法直接打开其他小程序。正确的实现方式是先从H5页面跳转回当前小程序&#xff0c;再由当前小程序跳转到目标小程序。具体实现方法如下&#xff1a; H5页面跳转回小程序时&#xff0c;调用wx.miniProgram.navigateTo()方法。 小程序跳转到…

ChatGPT 摘要,以 ESS 作为你的私有数据存储

作者&#xff1a;来自 Elastic Ryan_Earle 本教程介绍如何设置 Elasticsearch 网络爬虫&#xff0c;将网站索引到 Elasticsearch 中&#xff0c;然后利用 ChatGPT 使用我们的私人数据来总结对其提出的问题。 Python 脚本的 Github Repo&#xff1a;https://github.com/Gunner…

Linux系统的第一个进程是什么?

Linux进程的生命周期从创建开始&#xff0c;直至终止&#xff0c;贯穿了一个进程的整个存在过程。我们可以通过系统调用fork()或vfork()来创建一个新的子进程&#xff0c;这标志着一个新进程的诞生。 实际上&#xff0c;Linux系统中的所有进程都是由其父进程创建的。 既然所有…

《冲动》V1.6官方学习版

《冲动》官方版 https://pan.xunlei.com/s/VODiYvUAE1lECHcq66BR1np_A1?pwdfxc6# 具有侦探小说、戏剧和恐怖元素的惊悚片。 主角结束了漫长的商务旅行回到家&#xff0c;他的妻子和年幼的儿子热切地等待着他。然而&#xff0c;当他到达时&#xff0c;他发现有些不对劲&#x…

【Java计算机毕业设计】基于SSM圣宠宠物领养网站【源代码+数据库+LW文档+开题报告+答辩稿+部署教程+代码讲解】

源代码数据库LW文档&#xff08;1万字以上&#xff09;开题报告答辩稿 部署教程代码讲解代码时间修改教程 一、开发工具、运行环境、开发技术 开发工具 1、操作系统&#xff1a;Window操作系统 2、开发工具&#xff1a;IntelliJ IDEA或者Eclipse 3、数据库存储&#xff1a…

【微机原理与接口技术】定时控制接口

文章目录 8253的引脚和工作方式内部结构和引脚工作方式方式0&#xff1a;计数结束中断方式1&#xff1a;可编程单稳脉冲方式2&#xff1a;周期性负脉冲输出方式3&#xff1a;方波发生器方式4&#xff1a;软件触发的单次负脉冲输出方式5&#xff1a;硬件触发的单次负脉冲输出各种…

场馆预定平台高并发时间段预定实现V2

&#x1f3af; 本文档介绍了场馆预订系统接口V2的设计与实现&#xff0c;旨在解决V1版本中库存数据不一致及性能瓶颈的问题。通过引入令牌机制确保缓存和数据库库存的最终一致性&#xff0c;避免因服务器故障导致的库存错误占用问题。同时&#xff0c;采用消息队列异步处理库存…

从零到上线:Node.js 项目的完整部署流程(包含 Docker 和 CICD)

从零到上线&#xff1a;Node.js 项目的完整部署流程&#xff08;包含 Docker 和 CI/CD&#xff09; 目录 项目初始化&#xff1a;构建一个简单的 Node.js 应用设置 Docker 环境&#xff1a;容器化你的应用配置 CI/CD&#xff1a;自动化构建与部署上线前的最后检查&#xff1a;…

stm32 L051 adc配置及代码实例解析

一 cude的设置&#xff1a; 1. 接口的基本设置&#xff1a; 2. 参数的设置&#xff1a; 二 代码的逻辑&#xff1a; 1. 上面的直接生成代码&#xff0c;然后使用下面源码即可读到adc的数据&#xff1a; void adc_battery_start(void) {uint32_t ADC_value 0;HAL_ADC_Start(&…

【2024 博客之星评选】请继续保持Passion

我尝试复盘自己2024年走的路&#xff0c;希望能给诸君一些借鉴。 文章目录 回头望感想与收获成长与教训今年计划感恩一些体己话 回头望 回望我的2024年&#xff0c;年初拿高绩效&#xff0c;但感觉逐渐被公司一点点剥离出中心&#xff1b;年中一直在学习防患于未然&#xff1b…

【第二十周】U-Net:用于生物图像分割的卷积神经网络

文章目录 摘要Abstract文章信息研究动机U-Net网络结构U-Net网络搭建数据增强损失函数转置卷积创新性与不足创新性&#xff1a;不足&#xff1a; 总结 摘要 U-Net&#xff08;Convolutional Networks for Biomedical Image Segmentation&#xff09;是一种用于图像分割的深度学…