Java基础:设计模式之建造者模式

建造者模式是一种创建型设计模式,其主要目的是将一个复杂对象的构建过程与它的表示分离,使得同样的构建过程可以创建不同的表示。这种模式适用于创建那些包含多个组成部分、各部分之间有复杂的装配关系、且构造过程可能需要逐步进行或允许用户选择不同组件配置的产品对象。

结构与参与者

在建造者模式中,主要有以下几个关键角色:

  1. Product(产品类):定义了要构建的复杂对象的接口,通常包含多个组成部件。它不涉及具体的构建过程,仅定义产品的共有属性和行为。

  2. ConcreteProduct(具体产品类):实现了Product接口,是实际被构建的对象。

  3. Builder(抽象建造者):定义了一个包含一系列用于构建Product对象各个部件的抽象方法,通常还提供一个返回最终产品的接口(如getResult())。

  4. ConcreteBuilder(具体建造者):实现了Builder接口,负责实现构建过程的具体逻辑,即按照特定步骤创建并组装Product的各个部件。每个具体建造者都对应一种产品配置。

  5. Director(导演者/指挥者):负责协调建造过程,不直接参与对象的构建,而是通过调用Builder接口的方法来指导如何构建产品。它与具体的建造者解耦,使得客户端无需知道产品是如何被一步步构建出来的。

工作流程

  1. 客户端创建一个具体建造者(ConcreteBuilder)对象。
  2. 客户端通过Director以指定的步骤调用建造者的构建方法(如buildPartA(), buildPartB()等),逐步构建产品。
  3. 完成所有必要的构建步骤后,客户端可以通过建造者的getResult()方法获取最终构建好的Product对象。

示例说明

以创建一台电脑为例,我们可以定义如下类结构:

// Product: 电脑
public class Computer {private String cpu;private String memory;private String hardDisk;// 构造函数私有化,防止外界直接创建private Computer(String cpu, String memory, String hardDisk) {this.cpu = cpu;this.memory = memory;this.hardDisk = hardDisk;}// 提供获取电脑配置的getter方法// ...// 其他电脑相关的功能方法...
}// Builder: 抽象电脑建造者
public abstract class ComputerBuilder {protected Computer computer; // 用于保存中间构建结果public void createNewComputer() {computer = new Computer("", "", "");}public abstract void buildCPU(String cpu);public abstract void buildMemory(String memory);public abstract void buildHardDisk(String hardDisk);public Computer getComputer() {return computer;}
}// ConcreteBuilder: 高配电脑建造者
public class HighEndComputerBuilder extends ComputerBuilder {@Overridepublic void buildCPU(String cpu) {computer.setCPU(cpu);}@Overridepublic void buildMemory(String memory) {computer.setMemory(memory);}@Overridepublic void buildHardDisk(String hardDisk) {computer.setHardDisk(hardDisk);}
}// Director: 电脑装配厂
public class ComputerFactory {public Computer constructComputer(ComputerBuilder builder) {builder.createNewComputer();builder.buildCPU("Intel i9");builder.buildMemory("32GB DDR5");builder.buildHardDisk("1TB SSD");return builder.getComputer();}
}// 客户端使用
public class Client {public static void main(String[] args) {ComputerFactory factory = new ComputerFactory();ComputerBuilder builder = new HighEndComputerBuilder();Computer highEndComputer = factory.constructComputer(builder);System.out.println("Constructed high-end computer:");// 输出电脑配置...}
}

在这个例子中,Computer是产品类,ComputerBuilder是抽象建造者,HighEndComputerBuilder是具体建造者,ComputerFactory作为导演者角色,负责按照固定步骤调用建造者的构建方法来创建高配电脑。

适用场景

  1. 对象构造过程复杂:当一个对象的创建涉及多个步骤,这些步骤的顺序至关重要,或者某些步骤可能被省略,建造者模式能够清晰地封装这些复杂的构造逻辑。例如,创建一个包含多种零部件、配置选项多样的汽车、计算机或其他机械设备。

  2. 产品具有多种形态或配置:如果同一类型的产品可以根据客户需求或应用场景有不同的配置(如基础版、专业版、豪华版),每种配置对应一个具体建造者,这样可以方便地通过切换建造者来生成不同配置的产品,而无需在产品类中引入大量条件判断。

  3. 隔离复杂性:当产品类与创建过程过于复杂,以至于客户端代码难以理解或直接与之交互时,建造者模式可以将构建细节封装在建造者类中,使客户端只需与建造者接口交互,简化了客户端代码,同时隐藏了产品内部结构。

  4. 需要生成“零件列表”:在某些情况下,除了生成最终的产品对象外,还需要记录产品构建过程中使用的零件清单(如物料清单、成本计算等)。建造者模式可以在构建过程中收集这些信息,便于后续的报告生成或成本分析。

  5. 构建过程独立于产品组成部分:当构建过程独立于产品的具体组成部分(即构建算法与数据结构分离),且构建过程可能需要复用时,建造者模式能很好地分离这两部分,使得构建算法可以独立演化,提高代码的可维护性和扩展性。

  6. 需要支持递归构造:对于那些本身包含复杂树形结构或嵌套结构的产品(如XML文档、DOM树、菜单系统等),建造者模式可以自然地支持递归构造,通过递归调用建造者方法来构建嵌套结构。

  7. 需要延迟初始化:有时,出于性能、资源管理或依赖关系考虑,可能需要延迟初始化某些产品部件。建造者模式可以控制构建过程,确保在合适的时间点完成初始化。

存在的问题

尽管建造者模式能够有效地封装复杂对象的创建过程,但其使用也存在一些潜在问题:

  1. 代码膨胀:随着产品复杂性的增加,建造者类及其方法集可能会变得庞大,特别是当产品包含大量可选部件或配置时,可能会导致大量的建造者子类和构建方法。

  2. 过度设计:对于简单对象或者创建过程相对固定的场景,使用建造者模式可能会显得过于复杂,增加了不必要的抽象层次和类的数量。在这种情况下,简单的构造函数或者工厂方法可能就足够了。

  3. 灵活性与约束的平衡:为了保持构建过程的清晰和可控,建造者模式通常会限制客户端直接访问产品类的构造函数,这在一定程度上牺牲了灵活性。如果需要频繁改变产品的内部结构或添加新部件,可能需要修改建造者及其相关类。

  4. 适应变化的难度:当产品结构发生重大变化时,可能需要对所有的具体建造者进行相应的更新,这在大型项目中可能会带来一定的维护成本。

  5. 不适用动态产品结构:如果产品的组成部分或其组合方式在运行时才能确定,建造者模式可能不如其他动态生成对象的技术(如反射或脚本语言)灵活。

综上所述,建造者模式在处理复杂对象的创建、需要分步构建或支持多种不同配置的产品时非常有用,但应根据实际需求权衡其优点与可能带来的问题,避免在不需要复杂构建逻辑的情况下过度设计。

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

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

相关文章

笔记:编写程序,绘制一个展示支付宝月账单报告的饼图,

文章目录 前言一、饼图是什么?二、分析题目三、编写代码总结 前言 编写程序,绘制一个展示支付宝月账单报告的饼图,实现过程如下: (1) 导入 matplotlib.pyplot 模块; (2)…

《Fundamentals of Power Electronics》——三端电池的旋转、负载差分连接

以下是关于三端电池的旋转的相关知识点: Buck电路、Boost电路和Buck-Boost电路均包含一个与单刀单掷开关相连的电感。如下图所示。 将上图中的电感和开关网络视为一个标有a,b,c三端的基础电池。该电池在电源和负载之间有三种不同的连接方式。a-A b-B c-C连接方式组…

将要上市的自动驾驶新书《自动驾驶系统开发》中摘录片段

全书共分15章:第1章是自动驾驶系统的概述(场景分类、开发路径和数据闭环等),第2章简介自动驾驶的基础理论,即计算机视觉和深度学习等,第3~4章是自动驾驶的软硬件平台分析,包括传感器…

《动手学深度学习(Pytorch版)》Task02:预备知识——4.25打卡

《动手学深度学习(Pytorch版)》Task02:预备知识——4.25打卡 数据操作N维数组——张量创建数组访问元素入门初始化矩阵 运算符广播机制索引和切片节省内存转换为其他Python对象转换为NumPy张量ndarray张量转换为Python标量 数据预处理安装pan…

第一阶段--Day1--什么是网络安全?网络安全常用术语

目录 1. 什么是网络安全? 信息系统(Information System) 信息系统安全三要素(CIA) 网络空间安全管理流程 网络安全管理 2. 网络安全的常用术语 3. 网络安全形势 4. 中国网络安全产业现状 1. 什么是网络安全&am…

【面经】2024春招-后端开发工程师3(运营,安全,测开)

主要是面试前准备的相关材料与网络上的面经,个人不透露面试题目哈~ 文章目录 岗位与面经基础1:测试 & 测开 岗位与面经 1、腾讯云CSIG 星星海实验室2、小鹏汽车 【24届校招】后端研发工程师(销服方向) 广州正式研…

JFormDesigner 替换自定义类对象, code generation , custom creation code

JFormDesigner 文件的右侧 Code Generation -> Custom Creation Code 编辑写入 自定义的类对象

【一步一步了解Java系列】:探索Java基本类型与C语言的区别

看到这句话的时候证明:此刻你我都在努力~ 加油陌生人~ 个人主页: Gu Gu Study ​​ 专栏:一步一步了解Java 喜欢的一句话: 常常会回顾努力的自己,所以要为自己的努…

C++初阶之类和对象(下)

一、构造函数 1、构造函数体赋值 在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值。 class Date { public:Date(int year, int month, int day){_year year;_month month;_day day;} private:int _year;int _month;int _…

小程序API wx.startLocationUpdateBackground 的使用

若使用该接口,需要在 app.json 中进行声明 requiredPrivateInfos: [getLocation,onLocationChange,startLocationUpdate,startLocationUpdateBackground],requiredBackgroundModes: [audio,location],代码: 1、使用wx.startLocationUpdateBackground需要…

LeetCode 344.反转字符串

LeetCode 344.反转字符串 1、题目 题目链接:344. 反转字符串 编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。 不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一…

Java对象在堆和栈上的存储(对象布局,待完善)

0、前言 这里提到的 Java 对象不仅仅包含引用类型(Object),还包含基本数据类型(boolean、int、long、float、double)。文中部分图片来源于 B站 黑马程序员。 1、在栈上的数据存储 1.1、局部变量 局部变量包含以下情…

2024最新docker部署gitlab

docker部署gitlab 快速命令 1 拉取镜像 docker pull gitlab/gitlab-ce2 启动容器 docker run -itd \-p 9980:80 \-p 9922:22 \-v /opt/soft/docker/gitlab/etc:/etc/gitlab \-v /opt/soft/docker/gitlab/log:/var/log/gitlab \-v /opt/soft/docker/gitlab/opt:/var/opt/g…

20个 Golang 常见面试问题

1 Goroutine 在 Golang中的作用是什么? Goroutines 使得 Golang 能够并发执行多线程任务,允许函数在不相互阻塞的情况下同时运行。 2 如何在 Golang 中处理共享资源的并发访问? Golang 提供了同步原语,如互斥锁(mu…

Vite proxy-rewrite 属性详解

在前端开发中,为了避免跨域问题,我们会在vite.config.ts 中配置如下问题 rewrite: 由于不了解Nginx的知识,这个属性一直困扰着我,这个重写有啥用,加和不加有啥影响 server: {host: 0.0.0.0,proxy: {/api: {target: ht…

操作系统安全:安全审计,Windows系统日志详解,Windows事件ID汇总

「作者简介」:2022年北京冬奥会网络安全中国代表队,CSDN Top100,就职奇安信多年,以实战工作为基础对安全知识体系进行总结与归纳,著作适用于快速入门的 《网络安全自学教程》,内容涵盖系统安全、信息收集等…

从零开始安装 stable diffusion webui v1.9.3 (windows10)

从零开始安装 stable diffusion webui v1.9.3 (windows10) CUDA 安装 CUDA 12.1 | https://developer.nvidia.com/cuda-toolkit-archive CUDNN 8.x | https://developer.nvidia.com/rdp/cudnn-archive 安装路径 F:/CUDA/v12.1 安装git git官网 | https://git-scm.com/ 安…

数据结构-二叉搜索树(BST)

目录 什么是二叉搜索树 二叉搜索树的特性 (1)顺序性 (2)局限性 二叉搜索树的应用 二叉搜索树的操作 (1)查找节点 (2)插入节点 (3)删除节点 (4)中序遍历 什么是二叉搜索树 如图所示,二叉搜索树(binary search tree)满足以下条件。…

【EI会议|稳定检索】2024年航空航天、空气动力学与自动化工程国际会议(ICAAAE 2024)

2024 International Conference on Aerospace, Aerodynamics, and Automation Engineering 一、大会信息 会议名称:2024年航空航天、空气动力学与自动化工程国际会议 会议简称:ICAAAE 2024 收录检索:提交Ei Compendex,CPCI,CNKI,Google Schol…

WebGL开发框架比较

WebGL开发框架提供了一套丰富的工具和API,使得在Web浏览器中创建和操作3D图形变得更加容易。以下是一些流行的WebGL开发框架及其各自的优缺点。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎交流合作。 1.Three.js 优点&#xff1a…