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

news/2024/5/30 18:41:55/文章来源:https://blog.csdn.net/weixin_57057153/article/details/136589201

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

在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.luyixian.cn/news_show_1005974.aspx

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

相关文章

Three.js点线几何空间图形代码

Three.js点线几何空间图形代码。效果如下 下载地址 Three.js点线几何空间图形代码

Simple Admin:基于Go Zero的大型项目分布式微服务后端管理系统

Simple Admin 是一个开箱即用的分布式微服务后端管理系统,基于go-zero开发,为开发中大型后台提供了丰富的功能,支持三端代码生成。 官方自带多种扩展,助力中小企业快速上云,快速迭代。适合用于微服务学习和商用&#x…

【AI+编程】利用chatGPT编写python程序处理日常excel工作提升效率小技巧

之前写过一篇AI编程相关的文章 【人工智能】为啥我最近很少写python编程文章了,浅谈AI编程RPA提升工作效率 。 最近有同学私信我,怎么利用AI编程来提升工作效率,除了文章里讲的 使用AI帮忙写算法、代码提示、代码优化、不同语言转换(如J…

HTML静态网页成品作业(HTML+CSS)——电影加勒比海盗介绍设计制作(1个页面)

🎉不定期分享源码,关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 🏷️本套采用HTMLCSS,未使用Javacsript代码,共有1个页面。 二、作品演示 三、代…

Prompt进阶3:LangGPT(构建高性能质量Prompt策略和技巧2)--稳定高质量文案生成器

Prompt进阶3:LangGPT(构建高性能质量Prompt策略和技巧2)–稳定高质量文案生成器 1.LangGPT介绍 现有 Prompt 创建方法有如下缺点: 缺乏系统性:大多是细碎的规则,技巧,严重依赖个人经验缺乏灵活性:对他人分享的优质 …

Python之requests实现github模拟登录

文章目录 github 模拟登录前言模拟登录流程抓包操作查看登录表单的内容登录操作 模拟登录操作在 main函数的调用获得 auth_token调用/session接口登录处理检测登录是否成功 总结: github 模拟登录 前言 前面学习了requests模块的基础学习后,接下来做一个…

【开发】微服务整合Sentinel

目录 前言 1W:什么是Sentinel? 2W:为什么使用Sentinel? 3W:如何使用Sentinel? 1. 在pom.xml中导入Sentinel依赖坐标 2. 配置控制台 3. 访问API接口的任意端点 流量控制 1. 簇点链路 2. 快速入门…

springboot整合swagger,postman,接口规范

一、postman介绍 1.1概述 工具下载 Postman(发送 http 请求的工具) 官网(下载速度比较慢):Download Postman | Get Started for Free 网盘下载:百度网盘 请输入提取码 1.2Http 请求格式 请求地址请求方法状…

sqllab第六关通关笔记

知识点: 报错注入回顾原始语句测试截取函数 mid(字符串,起始位置,长度)substr(字符串,起始位置,长度)left(字符串,长度)right(字符串,长度)加入截取控制的错误注入payload payload:id1"%2…

在 Shell 中转换 Python 正则表达式

在Shell中,我们通常可以使用sed命令来转换Python正则表达式。sed是一个流编辑器,可以用来对文本进行替换、删除等操作。下面是一个示例,演示如何在Shell中将Python正则表达式转换为适用于sed的格式,也是比较稳妥的一种方式。 如上…

前端之用html做一个用户登陆界面

用户登陆界面 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>用户注册页面</title></head> <body><form action"https://www.baidu.com" method"post">…

opencv的approxPolyDP函数

cv2.approxPolyDP() 是 OpenCV 库中的一个函数&#xff0c;用于逼近多边形曲线。它可以将一条曲线用更少的点来表示&#xff0c;同时尽可能地保持其形状。原来是使用Douglas-Peucker算法&#xff0c;表示曲线上的点与逼近后的多边形之间的最大距离d&#xff0c;若d小于epsilon&…

如何恢复丢失未保存的 Word 文档指南

在广阔的数字领域&#xff0c;对丢失未保存的 Word 文档的恐惧对于用户来说是再熟悉不过的焦虑了。本指南旨在对用户可能发现自己迫切需要恢复未保存文档的各种场景进行详尽的探索。无论是由于保存失败、意外的系统崩溃还是令人心碎的意外删除&#xff0c;请放心&#xff0c;我…

【Vite+Ts】自动按需引入Element-Plus

安装插件 cnpm i -D unplugin-vue-components unplugin-auto-import unplugin-element-plus修改vite.config.ts // vite.config.ts import AutoImport from "unplugin-auto-import/vite"; import Components from "unplugin-vue-components/vite"; impor…

以太坊ETF获批将至

作者&#xff1a;BitMEX Research 编译&#xff1a;秦晋 摘要&#xff1a;在这篇文章中&#xff0c;我们讨论了以太坊ETF将在美国获得批准的可能性。我们尤其关注质押的经济学&#xff0c;以及缺乏收益率会如何在一定程度上削弱非质押以太坊ETF产品的吸引力。我们还研究了实施质…

CBNet(AAAI 2020)论文解析

paper&#xff1a;CBNet: A Novel Composite Backbone Network Architecture for Object Detection official implementation&#xff1a;GitHub - VDIGPKU/CBNet_caffe: Composite Backbone Network (AAAI20) 背景 一般来说&#xff0c;在基于CNN的目标检测模型中&#xff…

JAVA-网络编程基础

JAVA-网络编程 01. 网络通信 概念&#xff1a;两台设备之间通过网络实现数据传输网络通信&#xff1a;将数据通过网络从一台设备传输给另一台设备java.net包下提供了一系列类或接口&#xff0c;供程序员使用&#xff0c;完成网络通信 02. 网络 概念&#xff1a;两台设备或…

【PLIO学习总结】laserMapping中的时间戳与状态更新逻辑

本文仅用于个人学习总结记录。如有错误&#xff0c;请批评指正。 0、PLIO简要思路 从PLIO的论文中&#xff0c;可以知道&#xff0c;完整的PLIO算法采用IMU和LiDAR数据同时作为“输入”&#xff0c;维护状态变量包括加速度和角速度。 同时&#xff0c;PLIO是一种distortion-…

300分钟吃透分布式缓存-21讲:Redis读取请求数据后,如何进行协议解析和处理?

Redis 协议解析及处理 协议解析 上一课时讲到&#xff0c;请求命令进入&#xff0c;触发 IO 读事件后。client 会从连接文件描述符读取请求&#xff0c;并存入 client 的 query buffer 中。client 的读缓冲默认是 16KB&#xff0c;读取命令时&#xff0c;如果发现请求超过 1GB…

keycloak18.0.0==前后端分离项目中使用,前端react后端springboot

配置keycloak 启动keycloak18 新建一个realm,名字叫test1 新建两个client&#xff0c;一个用于前端&#xff0c;一个用于后端 第一个 react http://localhost:8081/auth/realms/test1/react/ 第二个 backend-service 在两个client下分别创建role testRole backend-servic…