当前位置: 首页 > news >正文

设计模式(四)创建型:生成器模式详解

设计模式(四)创建型:生成器模式详解

生成器模式(Builder Pattern)是 GoF 23 种设计模式中的核心创建型模式之一,其核心价值在于将一个复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建不同的表示。它特别适用于构造过程稳定但组成部分多变、配置参数繁杂的对象,如配置文件解析器、SQL 查询构造器、HTML 文档生成器、API 请求对象等。生成器模式通过分步构建对象并支持方法链式调用(Fluent Interface),极大提升了代码的可读性与可维护性。在现代框架中,该模式已演变为“流式 API”设计的基础,是构建复杂对象的优雅解决方案。

一、生成器模式详细介绍

生成器模式解决的是“复杂对象构造”中的常见痛点:当一个类的构造函数参数过多(尤其是存在大量可选参数)时,直接使用构造器或 setter 方法会导致代码冗长、易错且难以阅读。生成器模式通过引入一个独立的“生成器”对象,将对象的构建过程分解为多个清晰的步骤,最终通过 build() 方法一次性完成对象的创建。

该模式涉及以下关键角色:

  • Product(产品类):表示被构建的复杂对象。它通常具有多个组成部分或配置项,且构造过程较为复杂。该类的构造函数通常是私有的,防止外部直接实例化。
  • Builder(抽象生成器接口或抽象类):声明构建 Product 所需的各个构建步骤(如 setPartA()setPartB()),以及一个返回最终产品对象的 build() 方法。它定义了构建过程的契约。
  • ConcreteBuilder(具体生成器):实现 Builder 接口,负责具体地执行每一步构建操作,并维护一个 Product 实例的引用。它可以根据需要提供不同的构建逻辑,从而生成不同配置的 Product。
  • Director(指挥者,可选):负责调用 Builder 对象的各个构建方法,按照特定顺序执行构建流程。在许多现代实现中,Director 的职责被客户端直接承担,通过链式调用完成构建。

生成器模式的核心优势在于:

  • 解耦构建过程与表示:构建逻辑集中在 Builder 中,Product 类无需关心如何被创建。
  • 支持分步构建:允许逐步设置对象的各个部分,尤其适合依赖外部数据或条件判断的场景。
  • 实现不可变对象:Product 可以在构建完成后设为不可变(Immutable),提升线程安全性。
  • 支持方法链式调用:每个构建方法返回 this,实现流畅的 API 风格(Fluent API),如 builder.setA("a").setB("b").build()

与“工厂模式”相比,生成器更关注“如何构建”一个对象,而工厂关注“创建哪一个”对象。生成器适用于构建过程复杂、参数多变的场景,而工厂适用于类型选择明确的场景。

二、生成器模式的UML表示

以下是生成器模式的标准 UML 类图:

implements
creates
uses
constructed by
Product
-partA: String
-partB: int
-partC: boolean
+getPartA()
+getPartB()
+getPartC()
-Product(builder: Builder)
«abstract»
Builder
+setPartA(partA: String)
+setPartB(partB: int)
+setPartC(partC: boolean)
+build()
ConcreteBuilder
-partA: String
-partB: int
-partC: boolean
+setPartA(partA: String)
+setPartB(partB: int)
+setPartC(partC: boolean)
+build()
Director
-builder: Builder
+constructMinimal()
+constructFull()

图解说明

  • Product 是最终要构建的复杂对象,其构造函数为私有,只能通过 Builder 创建。
  • Builder 是抽象生成器,定义了设置各个部分的方法和 build() 方法。
  • ConcreteBuilder 实现 Builder,维护构建过程中的中间状态,并在 build() 中使用这些状态创建 Product
  • Director(可选)封装了标准的构建流程,如“最小构建”或“完整构建”。
  • 客户端可通过 ConcreteBuilder 链式调用设置参数,最后调用 build() 获取最终对象。

三、一个简单的Java程序实例

以下是一个基于生成器模式的 Java 示例,模拟构建一个 Email 对象:

// 产品类:Email
final class Email {private final String from;private final String to;private final String subject;private final String body;private final boolean isHtml;private final boolean isPriority;// 私有构造函数,只能通过 Builder 创建private Email(Builder builder) {this.from = builder.from;this.to = builder.to;this.subject = builder.subject;this.body = builder.body;this.isHtml = builder.isHtml;this.isPriority = builder.isPriority;}// Getter 方法public String getFrom() { return from; }public String getTo() { return to; }public String getSubject() { return subject; }public String getBody() { return body; }public boolean isHtml() { return isHtml; }public boolean isPriority() { return isPriority; }@Overridepublic String toString() {return "Email{" +"from='" + from + '\'' +", to='" + to + '\'' +", subject='" + subject + '\'' +", body='" + body + '\'' +", isHtml=" + isHtml +", isPriority=" + isPriority +'}';}// 静态内部生成器类public static class Builder {private String from;private String to;private String subject;private String body;private boolean isHtml = false;private boolean isPriority = false;public Builder from(String from) {this.from = from;return this; // 支持链式调用}public Builder to(String to) {this.to = to;return this;}public Builder subject(String subject) {this.subject = subject;return this;}public Builder body(String body) {this.body = body;return this;}public Builder html(boolean html) {this.isHtml = html;return this;}public Builder priority(boolean priority) {this.isPriority = priority;return this;}// 构建最终对象public Email build() {// 可在此处添加参数校验if (from == null || to == null || subject == null || body == null) {throw new IllegalStateException("Required fields (from, to, subject, body) must be set.");}return new Email(this);}}
}// 客户端使用示例
public class BuilderPatternDemo {public static void main(String[] args) {// 使用生成器构建一个普通邮件Email email1 = new Email.Builder().from("alice@example.com").to("bob@example.com").subject("Hello").body("This is a plain text email.").html(false).priority(false).build();System.out.println(email1);// 使用生成器构建一个高优先级 HTML 邮件Email email2 = new Email.Builder().from("admin@system.com").to("user@company.com").subject("Urgent: System Alert").body("<h1>CRITICAL ALERT!</h1><p>Server is down.</p>").html(true).priority(true).build();System.out.println(email2);}
}

运行说明

  • Email 类是不可变的,所有字段在构建后不可更改。
  • Builder 类提供链式方法设置各个字段,最后调用 build() 创建 Email 实例。
  • 客户端代码清晰、易读,避免了长参数列表或 setter 的繁琐调用。
  • build() 方法中可加入参数校验,确保对象的完整性。

四、总结

生成器模式通过引入独立的构建过程,成功解决了复杂对象构造的难题:

  • 提升可读性:链式调用使代码像自然语言一样流畅。
  • 支持可选参数:无需为不同参数组合定义多个构造函数(避免“伸缩构造器反模式”)。
  • 保证对象完整性:可在 build() 阶段集中校验参数,防止创建不合法对象。
  • 支持不可变性:Product 可设计为不可变对象,增强线程安全。

但也存在缺点:

  • 增加类复杂度:需要为每个复杂类定义一个 Builder。
  • 不适合简单对象:对于字段少、构造简单的类,使用 Builder 反而增加冗余。

因此,应在“对象复杂度”与“代码简洁性”之间权衡使用。

架构师洞见:
生成器模式是现代 API 设计的“黄金标准”。在 Spring、OkHttp、JPA Criteria API 等主流框架中,流式构建(Fluent Builder)已成为标配。架构师应认识到:生成器不仅是创建对象的工具,更是一种提升开发者体验(DX)的设计哲学。它通过“意图清晰的 API”降低使用门槛,减少错误。未来,随着 DSL(领域特定语言)和代码生成技术的发展,生成器将进一步自动化——通过注解处理器或 APT 自动生成 Builder 代码,消除样板代码。掌握生成器模式,有助于设计出既强大又易用的内部组件与公共 API,是构建高质量、可维护系统的关键能力。在微服务配置、消息构造、查询构建等高频场景中,生成器模式的价值尤为突出。

http://www.xdnf.cn/news/1201483.html

相关文章:

  • Java排序中(a).compareTo(b)与Integer.compare(a, b)区别
  • 推荐系统学习
  • 算法竞赛阶段二-数据结构(37)数据结构循环链表模拟实现
  • 【PCIe 总线及设备入门学习专栏 5.3.4 -- PCIe PHY Firmware 固件加载流程】
  • Android启动时间优化大全
  • 通信名词解释:I2C、USART、SPI、RS232、RS485、CAN、TCP/IP、SOCKET、modbus等
  • Window 部署 coze-stdio(coze 开发平台)
  • vue3.6更新哪些内容
  • 电子电路设计学习
  • MySQL - 索引(B+树)
  • Python Pandas.cut函数解析与实战教程
  • 力扣热题100----------41.缺少的第一个正数
  • C++算法竞赛篇(五)循环嵌套题型讲解
  • JavaScript手录07-数组
  • JavaScript核心概念全解析
  • 创建属于自己的github Page主页
  • 【Python系列】Flask 应用中的主动垃圾回收
  • 安装redis
  • 生成式召回-TIGER范式
  • Vim 编辑器工作模式及操作指南
  • 抗辐照芯片在低轨卫星星座CAN总线通讯及供电系统的应用探讨
  • 比特币运行机制全解析:区块链、共识算法与数字黄金的未来挑战
  • rapidocr v3.3.0发布了
  • OpenLayers 综合案例-轨迹回放
  • Torchv Unstrustured 文档解析库
  • C语言:函数
  • C/C++核心知识点详解
  • Qt C++ GUI 函数参数速查手册:基础与布局
  • RK3568 Linux驱动学习——Linux驱动开发准备工作
  • 【科研绘图系列】R语言绘制边际云雨图散点图