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

embedded/2024/10/19 5:31:25/

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

结构与参与者

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

  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对象。

示例说明

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

java">// 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.ppmy.cn/embedded/25471.html

相关文章

LinkedList与链表

文章目录 ArrayList的缺陷链表链表的概念及结构链表的实现 LinkedList的使用什么是LinkedListLinkedList具体使用 ArrayList和LinkedList的区别 ArrayList的缺陷 通过源码知道,ArrayList底层使用数组来存储元素 由于其底层是一段连续空间,当在ArrayList任…

Three.js杂记(十四)———— 汽车展览·上

在学习了一些理论知识后,要做一下实战演练了,做一个简单的车辆展览来看看吧。 通过调整相机的位置,将导入的车辆模型分成三个视角展示。 车辆外部:可以观察车辆的整体外观以及轮廓结构车辆内部:相机在汽车内部&#…

DataV的轮播表后端返回的数据处理

由于官网上DataV的轮播表的接收data格式为: export default {data: [[行1列1, 行1列2, 行1列3],[行2列1, 行2列2, 行2列3],[行3列1, 行3列2, 行3列3],[行4列1, 行4列2, 行4列3],[行5列1, 行5列2, 行5列3],[行6列1, 行6列2, 行6列3],[行7列1, 行7列2, 行7列3],[行8列1, 行8列2,…

现代机器学习(ML)技术在医疗成像领域的新应用

现代机器学习(ML)技术在医疗成像领域的新应用主要包括以下几个方面: 一、自动病变检测 使用深度学习算法,尤其是卷积神经网络(CNN),自动识别和分类医学影像中的病变,如肿瘤、炎症等。自动病变检测是现代机器学习技术在医疗成像领域应用的一个重要方向。它主要通过以下…

使用 Docker 自建一款怀旧游戏之 - 扫雷

1)扫雷 简介 扫雷 是一种经典的单人电脑游戏,最初由微软公司在 1990 年代开发并内置在 Windows 操作系统中。游戏的目标是在一个由方块组成的网格上揭开所有非地雷的方块,而不触发地雷。每个方块上都标有数字,表示周围 8 个方块中…

Python urllib 爬虫入门(1)

本文主要为Python urllib类库函数和属性介绍及一些简单示例。 目录 urllib爬取网页 简单示例 写入文件 其他读取方法 readline函数 readlines函数 response属性 当前环境信息 返回状态码 返回url地址 对url进行编码与解码 写入文件 总结 urllib爬取网页 通过pyth…

混合A* 中基于 Voronoi 势场的路径代价和 Voronoi 势场的实现测试

参考 Practical Search Techniques in Path Planning for Autonomous Driving 混合 A* 论文 Sensor-Based Exploration: The Hierarchical Generalized Voronoi Graph Voronoi 图论文 认识 Voronoi ,泰森多边形 voronoi 介绍和应用 Voronoi Field 和 Voronoi Dia…

【数据结构】顺序表专题

前言 本篇文章我们来进行有关顺序表的专题训练,让我们一起来看一下有关顺序表的算法题 💓 个人主页:小张同学zkf ⏩ 文章专栏:数据结构 📝若有问题 评论区见 🎉欢迎大家点赞👍收藏⭐文章 1.移除…