当前位置: 首页 > 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.dtcms.com/a/300850.html

相关文章:

  • 设计模式(三)创建型:抽象工厂模式详解
  • 第五章第二节 对射式红外传感器计次旋转编码器计次
  • 8.c语言指针
  • 标签驱动的可信金融大模型训练全流程-Agentar-Fin-R1工程思路浅尝
  • AI驱动的金融推理:Fin-R1模型如何重塑行业决策逻辑
  • JSON格式化与结构对比
  • 2025年量子计算与前沿技术融合:六大变革性方向深度解析
  • Rust实战:高效开发技巧
  • 02人工智能中优雅草商业实战项目视频字幕翻译以及声音转译之以三方AI模型API制作方式预算-卓伊凡|莉莉
  • 【在Unity游戏开发中Dictionary、List介绍】
  • 基于Springboot+UniApp+Ai实现模拟面试小工具七:前端项目创建及框架搭建
  • 深入理解 Spring 中的 XmlBeanFactory 原理及实践
  • 【最新版】防伪溯源一体化管理系统+uniapp前端+搭建教程
  • ArKTS:List 数组
  • 机器学习特征选择 explanation and illustration of ANOVA
  • ROS2总结(二)
  • UDS 0x29 身份验证服务 Authentication service
  • Rust Web 全栈开发(十一):WebAssembly 尝鲜
  • 2507rust,rust写驱动
  • rust- 定义模块以控制作用域和隐私
  • 无刷电机三项霍尔连接线序组合详细分析与波形实例
  • ETF历史每笔成交分钟级高频数据深度解析
  • 墨者:通过手工解决SQL手工注入漏洞测试(MongoDB数据库)
  • Rust与Java DynamoDB、MySQL CRM、tokio-pg、SVM、Custors实战指南
  • 零基础 “入坑” Java--- 十四、字符串String
  • mybatis-plus实体类主键生成策略
  • 使用uni-app开发一个点餐收银台系统前端静态项目练习
  • 车辆网络安全规定之R155与ISO/SAE 21434
  • 09_opencv_遍历操作图像像素
  • uniapp input 聚焦时键盘弹起滚动到对应的部分