掌握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. 构造过程不同:建造者模式注重的是部件构建的过程,旨在通过一步一步地精确构造创建出一个复杂的对象。工厂模式一般都是创建一个产品,注重的是把这个产品创建出来就行,只要创建出来,不关心这个产品的组成部分。

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

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

相关文章

Android Studio Iguana | 2023.2.1版本

Android Gradle 插件和 Android Studio 兼容性 Android Studio 构建系统基于 Gradle,并且 Android Gradle 插件 (AGP) 添加了一些特定于构建 Android 应用程序的功能。下表列出了每个版本的 Android Studio 所需的 AGP 版本。 如果特定版本的 Android Studio 不支持…

如何将MathType嵌入到word中 word打开MathType显示错误

当我们编辑好mathtype公式以后,有时候需要将这个公式导入到word中,但是有不少用户们不清楚mathtype如何嵌入到word中。今天小编就给大家说明一下mathtype公式导入word的两种不同方法,有需要的用户们赶紧来看一下吧。 一、mathtype如何嵌入到…

C++流行的开源框架和库总结

目录 引言: 标准库 框架C通用框架和库 人工智能与机器人学习 异步事件循环 音视频多媒体 压缩压缩和归档库 并发性并发执行和多线程 容器 密码学 数据库,SQL服务器,ODBC驱动程序和工具 游戏引擎 图形与图像 国际化 Json 日志…

Java - JVM

文章目录 一、JVM1. JVM的作用2. JVM、JRE、JDK的关系3. JVM的组成4. JVM工作流程5. 运行时方法区Runtime Data Area 二、深入JVM内存模型(JMM) 一、JVM 1. JVM的作用 Java代码编译成java字节码后,运行在JVM中,只要针对不同的系统…

保姆级讲解 Stable Diffusion

目录 本文讲解思路介绍 一、引入 二、Diffusion Model 三、原文的摘要和简介 四、Stable Diffusion 4.1、组成模块 4.2、感知压缩 4.3、条件控制 五、图解 Stable Diffusion 5.1、潜在空间的扩散 5.2、条件控制 5.3、采样 5.4、Diffusion Model 与 Stable Diffusion …

OnlyFans如何微信支付?订阅Onlyfans虚拟卡?OnlyFans订阅推荐指南教程

OnlyFans 订阅教程,手把手教你使用虚拟信用卡订阅 大家好,大家都在关心OnlyFans如何订阅怎么订阅,能不能用微信或者支付宝来订阅,首先微信是不行的,本文教大家如何在 Onlyfans 订阅和支付(虚拟信用卡&#…

【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/…

R语言基础的代码语法解译笔记

1、双冒号,即:“::” 要使用某个包里的函数,通常做法是先加载(library)包,再调用函数。最新加载的包的namespace会成为最新的enviroment,某些情况下可能影响函数的结果。而package name::funct…

java ~ word模板填充字符后输出到指定目录

word文件格式&#xff1a; jar包&#xff1a; <dependency><groupId>com.deepoove</groupId><artifactId>poi-tl</artifactId><version>1.10.0</version></dependency>样例代码&#xff1a; // 封装参数集合Map<String, Ob…

报告,已成功揪出三害:英语、谷歌、ChatGPT

互联网风云变幻&#xff0c;最近网上的壮士们经过不懈努力&#xff0c;成功揪出作家莫言为一害&#xff0c;微博上的壮士们给出的理由是“如果莫言是个好人&#xff0c;会给他发诺贝尔文学奖&#xff1f;” 此风波的始作俑者来自某大V&#xff0c;他信誓旦旦要起诉莫言老师&…

Java实现从本地读取CSV文件数据

一、前言 最近项目中需要实现这样一个功能&#xff0c;就是从本地读取CSV文件&#xff0c;并以指定行作为标题行&#xff0c;指定行开始作为数据读取行&#xff0c;读取数据并返回给前端&#xff0c;下面具体说下是如何通过java实现。 二、如何实现&#xff1f; 1.引入相关mav…

【深度学习笔记】6_7 门控循环单元(GRU)

注&#xff1a;本文为《动手学深度学习》开源内容&#xff0c;部分标注了个人理解&#xff0c;仅为个人学习记录&#xff0c;无抄袭搬运意图 6.7 门控循环单元&#xff08;GRU&#xff09; 上一节介绍了循环神经网络中的梯度计算方法。我们发现&#xff0c;当时间步数较大或者…

【Objective -- C】—— 自引用计数

【Objective -- C】—— 自引用计数 一. 内存管理/自引用计数1.自引用计数2.内存管理的思考方式自己生成的对象&#xff0c;自己持有非自己生成的对象&#xff0c;自己也能持有不再需要自己持有的对象时释放无法释放非自己持有的对象 3.alloc/retain/release/dealloc实现4. aut…

全链路Python环境迁移

全链路Python环境迁移 在当前的Python环境中&#xff0c;安装一些库以后&#xff0c;如果换了一套Python环境&#xff0c;难道再来一次不停的pip install&#xff1f;当然不是。 第一步&#xff0c;使用pip freeze&#xff08;冻结&#xff09;备份当前Python库的环境 pip f…

智慧公厕系统的运作过程

智慧公厕是一种新型的未来城市公共厕所&#xff0c;通过物联网、互联网、大数据、云计算、自动化控制等技术&#xff0c;实现公共厕所使用、运营、管理、养护的全过程全方位信息化。 那么&#xff0c;智慧公厕是如何运作的&#xff1f;智慧公厕的运作过程包括什么技术&#xf…

【Pytorch、torchvision、CUDA 各个版本对应关系以及安装指令】

Pytorch、torchvision、CUDA 各个版本对应关系以及安装指令 1、名词解释 1.1 CUDA CUDA&#xff08;Compute Unified Device Architecture&#xff09;是由NVIDIA开发的用于并行计算的平台和编程模型。CUDA旨在利用NVIDIA GPU&#xff08;图形处理单元&#xff09;的强大计算…

使用R语言进行聚类分析

一、样本数据描述 城镇居民人均消费支出水平包括食品、衣着、居住、生活用品及服务、通信、文教娱乐、医疗保健和其他用品及服务支出这八项指标来描述。表中列出了2016年我国分地区的城镇居民的人均消费支出的原始数据&#xff0c;数据来源于2017年的《中国统计年鉴》&#xf…

Publii和GitHub:搭建个人网站的完美组合

在数字时代&#xff0c;拥有一个个人网站已经非常普遍了&#xff0c;但是&#xff0c;很多人因为技术难题而望而却步。现在&#xff0c;有了Publii&#xff0c;这一切都将变得简单。Publii是一个静态网站生成器&#xff0c;它允许你在本地计算机上创建和管理内容&#xff0c;然…

ARM中汇编语言的学习(加法、乘法、除法、左移、右移、按位与等多种命令操作实例以及ARM的 N、Z、C、V 标志位的解释)

汇编概述 汇编需要学习的大致框架如下&#xff1a; 汇编中的符号 1.指令&#xff1b;能够北嘁肷梢惶?2bit机器码&#xff0c;并且能够被cpui识别和执行 2.伪指令&#xff1a;本身不是指令&#xff0c;编译器可以将其替换成若干条指令 3.伪操作&#xff1a;不会生成指令…

如何修复advapi32.dll丢失无法启动程序的问题

如果你在运行Windows程序时遇到了“advapi32.dll丢失无法启动程序”的错误消息&#xff0c;那么这意味着你的计算机缺少这个DLL文件。在本文中&#xff0c;我们将提供一些解决方案&#xff0c;帮助你解决这个问题并恢复计算机的正常运行。 一.advapi32.dll丢失电脑的提示 关于…