掌握Java建造者模式:逐步构建复杂对象的艺术与实践

建造者模式的主要目的是将一个复杂对象的构建过程封装起来,使得客户端代码不需要知道对象创建的细节。这种模式特别适用于那些具有多个组成部分、创建过程复杂、对象属性多且大多数属性可选的场合。

在Java中,建造者模式通常涉及以下几个角色:

  • Builder(建造者):为创建一个Product对象的各个部件指定抽象接口。
  • ConcreteBuilder(具体建造者):实现Builder的接口以构造和装配该产品的各个部件。定义并明确它所创建的表示,并提供一个检索产品的接口。
  • Director(指挥者):构造一个使用Builder接口的对象。
  • Product(产品):表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程。
  • Client(客户端):创建一个Director对象,并用它所想要的Builder对象来配置。

以下是建造示例产品的代码:Product类表示复杂对象,Builder类是抽象建造者类,ConcreteBuilder1和ConcreteBuilder2是具体的建造者类,buildPartA;b;c用来代指构建产品的不同部分,Director类负责指挥构建过程,Client类是客户端代码。
我们用图像来表示各个类之间的关系:
在这里插入图片描述

先构建Product产品类:

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;
    }

    public void show() {
        System.out.println("Product: " + partA + ", " + partB + ", " + partC);
    }
}

抽象建造者类:

abstract class Builder {
    protected Product product = new Product();

    public abstract void buildPartA();
    public abstract void buildPartB();
    public abstract void buildPartC();

    public Product getResult() {
        return product;
    }
}

具体建造者类1:

class ConcreteBuilder1 extends Builder {
    public void buildPartA() {
        product.setPartA("Part A1");
    }

    public void buildPartB() {
        product.setPartB("Part B1");
    }

    public void buildPartC() {
        product.setPartC("Part C1");
    }
}

具体建造者类2:

class ConcreteBuilder2 extends Builder {
    public void buildPartA() {
        product.setPartA("Part A2");
    }

    public void buildPartB() {
        product.setPartB("Part B2");
    }

    public void buildPartC() {
        product.setPartC("Part C2");
    }
}

指挥者类:

class Director {
    private Builder builder;

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

    public void construct() {
        builder.buildPartA();
        builder.buildPartB();
        builder.buildPartC();
    }
}

客户端代码:

public class BuilderPatternDemo {
    public static void main(String[] args) {
        Builder builder1 = new ConcreteBuilder1();
        Director director1 = new Director(builder1);
        director1.construct();
        Product product1 = builder1.getResult();
        product1.show();

        Builder builder2 = new ConcreteBuilder2();
        Director director2 = new Director(builder2);
        director2.construct();
        Product product2 = builder2.getResult();
        product2.show();
    }
}

适用场景

  1. 对象结构复杂:当一个对象有很多属性,且内部结构非常复杂时,使用建造者模式可以将这些属性的构建过程封装起来,使得客户端代码不需要直接处理这些复杂性。
  2. 构建步骤多:如果创建一个对象需要很多步骤,尤其是在这些步骤之间有依赖关系或者某些步骤可以省略时,建造者模式可以将这些步骤分离,使得每一步都可以独立执行,同时也允许不同的步骤组合来创建不同的对象表示。
  3. 创建与使用分离:在希望将对象的创建过程与它的使用过程分离时,建造者模式提供了一种机制,使得客户端代码可以在不了解对象内部细节的情况下,通过指定的步骤创建出所需的对象。

JDK中的建造者模式

  1. StringBuilder 类:StringBuilder 类提供了 append() 方法,允许链式调用来构建字符串。这种方式避免了多次创建字符串对象,提高了效率。StringBuilder 就是通过建造者模式来实现这一链式创建对象的过程。
  2. ProcessBuilder 类:ProcessBuilder 类用于创建操作系统进程。它也提供了一种流畅的接口,允许开发者通过连续调用方法来设置进程的各种属性,最后通过 start() 方法来启动进程。ProcessBuilder 的这种使用方式也是建造者模式的一个体现。

优点

  1. 封装性良好:建造者模式通过将复杂对象的创建过程封装在建造者类中,实现了创建过程和使用过程的分离。这样做的好处是,客户端代码不需要知道对象是如何一步步构建起来的,只需要知道如何组合这些步骤即可。这不仅使得客户端代码更加简洁,也降低了出错的可能性。
  2. 扩展性良好:由于建造者类之间相互独立,这在一定程度上实现了解耦。当需要增加新的构建步骤或者修改现有步骤时,只需修改相应的建造者类,而不影响其他类。这种设计提高了系统的可维护性和可扩展性。
  3. 简化复杂对象的创建:对于参数多、校验复杂的对象创建过程,建造者模式提供了一种清晰且易于理解的方式来逐步构建对象。这种方法特别适用于那些构造函数参数众多,或者对象创建过程需要多个步骤的情况。
  4. 提高代码的可读性和可维护性:建造者模式使得代码的结构更加清晰,每个建造者类负责一部分构建逻辑,这有助于提高代码的可读性和可维护性。

缺点

  1. 增加类的数量:为了实现复杂对象的构建,可能需要引入多个建造者类,这会增加系统中类的总数。
  2. 内部修改困难:如果产品类的内部结构或构建过程发生变化,可能需要修改建造者类,这可能会导致维护上的困难。
  3. 范围限制:建造者模式要求产品具有共同点,这限制了它的使用范围。如果产品的内部变化非常复杂,可能会导致建造者类的数量增加,从而使得系统变得更加复杂。

建造者模式和工厂模式区别

  1. 目的不同:建造者模式关注于创建复杂对象的构建过程,将构建过程和表示分离,以便可以逐步构建复杂对象。工厂模式关注于对象的创建,将对象的创建过程封装在工厂中,以便在客户端中使用。
  2. 构造过程不同:建造者模式注重的是部件构建的过程,旨在通过一步一步地精确构造创建出一个复杂的对象。工厂模式一般都是创建一个产品,注重的是把这个产品创建出来就行,只要创建出来,不关心这个产品的组成部分。

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

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

相关文章

Day29:安全开发-JS应用DOM树加密编码库断点调试逆向分析元素属性操作

目录 JS原生开发-DOM树-用户交互 JS导入库开发-编码加密-逆向调试 思维导图 JS知识点: 功能:登录验证,文件操作,SQL操作,云应用接入,框架开发,打包器使用等 技术:原生开发&#x…

SLAM|初识SLAM

在空间中,人可以通过固定不动的事物来作为参考系中的参照物。 而这些固定不动的东西可以称之为特征,空间可以理解成特征存在的空间。 而参照物的意义,可以变成是看到某某参照物,就按这个某某参照物进行位置移动。 比如说碰到这个…

【SQL】550. 游戏玩法分析 IV (关键点:确定连续两次登录)

前述 常见函数用法示例: DATEDIFF(col1, col2) 1DATE_ADD(MIN(col), INTERVAL 1 DAY)ROUND(3.1415926,3) > 四舍五入得到 3.142 题目描述 leetcode原题:550. 游戏玩法分析 IV 思路 确定连续两次登录统计,保留两位小数 写法一 关键…

【Tauri】(4):使用Tauri1.5版本+candle框架运行大模型,前后的搭建运行成功,整合前端项目,在应用中显示。

1,视频地址 关于tauri 框架 2,搭建rust 环境 # 设置服务器国内代理: export RUSTUP_DIST_SERVER"https://rsproxy.cn" export RUSTUP_UPDATE_ROOT"https://rsproxy.cn/rustup"# 设置环境变量 export RUSTUP_HOME/data/…

【Haproxy】Haproxy的配置和应用

HAProxy介绍 HAProxy是法国开发者威利塔罗(Willy Tarreau)在2000年使用C语言开发的一个开源软件,是一款具备高并发(一万以上)、高性能的TCP和HTTP负载均衡器,支持基于cookie的持久性,自动故障切换,支持正则表达式及web状态统计&a…

HCIA-HarmonyOS设备开发认证V2.0-习题2

目录 习题一习题二坚持就有收获 习题一 # 判断题## 1.PWM占空比指的是低电平时间占周期时间的百分比。(错误)正确(True)错误(False)解题: - PWM占空比指的是高电平时间占周期时间的百分比## 2.UART是通用异步收发传输器,是通用串行数据总线,…

微服务技术栈SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式(四):消息队列MQ

文章目录 一、消息队列MQ二、RabbitMQ2.1 单机部署2.2 消息模型 三、SpringAMAP3.1 简单消息队列3.2 工作消息队列3.3 发布-订阅模型:FanoutExchange 广播交换机3.4 发布-订阅模型:DirectExchange 路由交换机3.5 发布-订阅模型:TopicExchange…

Ubuntu平铺左、右、上、下、1/2、1/4窗口(脚本)

前言 之前因为一直在用Ubuntu 18或者Ubuntu 20然后发现装了GNOME插件后,电脑在使用过程中,会时不时的卡死(鼠标没问题,键盘输入会有10-20秒的延迟)频率基本是一小时一次,因为这种卡顿会很容易打断思路&…

【职言】三年功能测试,一些测试工作的“吐槽”

以下为作者观点: 概述 作为功能测试,我也分享下日常工作中功能测试值得吐槽的问题,由于工作时间不长且未进过大厂,不了解大公司的工作模式和流程,所以自己的方法和理解都是基于中小公司的工作经验总结,应…

Linux 之五:权限管理(文件权限和用户管理)

1. 文件权限 在Linux系统中,文件权限是一个非常基础且重要的安全机制。它决定了用户和用户组对文件或目录的访问控制级别。 每个文件或目录都有一个包含9个字符的权限模式,这些字符分为三组,每组三个字符,分别对应文件所有者的权限…

2024蓝桥杯每日一题(差分)

一、第一题:空调 解题思路:差分 希望P减掉T后就相当于从0到New_P,想到得到New_P只需要对全0数组进行若干次区间加操作,所以只需要对New_P数组进行差分,累加正数和负数,哪个绝对值大答案就是那个。 …

【深度学习笔记】6_8 长短期记忆(LSTM)

注:本文为《动手学深度学习》开源内容,部分标注了个人理解,仅为个人学习记录,无抄袭搬运意图 6.8 长短期记忆(LSTM) 本节将介绍另一种常用的门控循环神经网络:长短期记忆(long shor…

二叉树的先序遍历详解(小白也懂)(附带中序,后序代码)

文章目录 二叉树的先序遍历(分而治之思想)样例图函数的递归调用源代码运行结果 二叉树的先序遍历(分而治之思想) 代码在文章底部。 先序遍历又叫先根遍历,顾名思义:遍历顺序为根,左子树,右子树。 样例图 本文将对以下二叉树进…

关于 JVM

1、请你谈谈你对JVM的理解? JVM由JVM运行时数据区(图示中蓝色框包含部分)、执行引擎、本地库接口、本地方法库组成。 JVM运行时数据区,分为方法区、堆、虚拟机栈、本地方法栈和程序计数器。 1.方法区 Java 虚拟机规范中定…

YOLOv8-Seg改进:SPPF涨点篇 |引入YOLOv9的SPPELAN

🚀🚀🚀本文改进:SPP创新结合ELAN,来自于YOLOv9,助力YOLOv8,将SPPELAN代替原始的SPPF 🚀🚀🚀YOLOv8-seg创新专栏:http://t.csdnimg.cn/KLSdv 学姐带你学习YOLOv8,从入门到创新,轻轻松松搞定科研; 1)手把手教你如何训练YOLOv8-seg; 2)模型创新,提升分割…

day59 线程

创建线程的第二种方式 实现接口Runnable 重写run方法 创建线程的第三种方式 java.util.concurrent下的Callable重写call()方法 java.util.concurrent.FutureTask 创建线程类对象 获取返回值 线程的四种生命周期 线程的优先级1-10 default为5,优先级越高&#xff0c…

JavaEE进阶(15)Spring原理:Bean的作用域、Bean的生命周期、Spring Boot自动配置(加载Bean、SpringBoot原理分析)

接上次博客:JavaEE进阶(14)Linux基本使用和程序部署(博客系统部署)-CSDN博客 目录 关于Bean的作用域 概念 Bean的作用域 Bean的生命周期 源码阅读 Spring Boot自动配置 Spring 加载Bean 问题描述 原因分析 …

JavaEE企业开发新技术

目录 2.1 Class对象基本概念 1、概念 2.2 Class对象的获取方式 2.3基本数据类型的Class对象 1、概念 2.4 反射的基本概念 概念 2.5 Class对象的基本使用-1 2.6 Class对象的基本使用-2 newInstance()和new()区别: 2.1 Class对象基本概念 1、概念 反射的…

面试经典150题——合并两个有序链表

You just work on it. Time will do the rest! 1. 题目描述 2. 题目分析与解析 2.1 思路一 这个题目还是比较简单的,通过分析题目,我们可以知道题目中关键信息为: 所以我们只需要从前向后遍历两个链表,在两个链表不空的情况下&…

白皮书发布|超融合运行 K8s 的场景、功能与优势

目前,不少企业都使用虚拟化/超融合运行 Kubernetes 和容器化应用。一些用户可能会有疑惑:既然 Kubernetes 可以部署在裸金属上,使用虚拟化不是“多此一举”吗? 在电子书《IT 基础架构团队的 Kubernetes 管理:从入门到…