Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

05_构建者模式 Builder Pattern

1. 基本信息

中文名称: 构建者模式

英文名称: Builder Pattern

模式类型: 创建型设计模式

Rust 中常见实现方式: Builder 链式调用、struct + implOption 字段、默认值、方法链、build() 最终生成结构体

构建者模式的核心是:将复杂对象的构造过程抽象出来,使对象可以按步骤构造,同时允许灵活组合属性和可选字段。

在 Rust 中,构建者模式通常结合结构体和方法链实现,使得创建复杂对象既清晰又安全。

示例代码


2. 模式核心思想

构建者模式的核心思想是:

将对象构造过程和对象本身分离,让调用者可以按步骤设置不同字段,最终生成完整对象。

它关注的核心问题是:

对象属性众多或复杂,直接构造难以管理
部分字段可选,部分字段必填
希望代码表达清晰,避免大量重复构造逻辑

3. 这个模式解决什么问题

在实际开发中,构建者模式常用于以下场景:

配置对象有很多字段,且部分可选
HTTP 请求或数据库查询参数对象需要灵活组合
对象初始化涉及复杂默认值或计算
对象构造步骤多,需要顺序控制
API 客户端、任务配置或复杂结构体的初始化

使用构建者模式可以让调用者只关心要设置哪些属性,不必了解完整的初始化细节。


4. 不使用这个模式会怎样

如果不使用构建者模式,可能出现:

调用方必须直接使用长参数列表的构造函数,容易出错
默认值逻辑散落在各处
可选字段需要写很多重复的 if/else
构造复杂对象的代码冗长且难以阅读
修改对象初始化逻辑时,需要修改多个构造位置

5. 传统面向对象中的实现思路

在传统 OOP 语言中,构建者模式通常包含以下角色:

Builder:定义构建步骤接口
ConcreteBuilder:实现具体构建步骤
Director:负责调用 Builder 完成构造
Product:最终生成的复杂对象

调用方通过 Director 或直接使用 Builder 设置各个属性,最后调用 build() 获取完整对象。

典型结构图示:

Client
 └─ Builder
      ├─ set_part_a()
      ├─ set_part_b()
      └─ build() -> Product

6. Rust 中的实现思路

6.1 Rust 中通常怎么实现

在 Rust 中,构建者模式通常用结构体 + 方法链实现:

struct ServerConfig {
    host: String,
    port: u16,
    use_tls: bool,
    timeout: Option<u64>,
}

struct ServerConfigBuilder {
    host: String,
    port: u16,
    use_tls: bool,
    timeout: Option<u64>,
}

impl ServerConfigBuilder {
    fn new() -> Self { ... }
    fn host(mut self, host: &str) -> Self { ... }
    fn port(mut self, port: u16) -> Self { ... }
    fn use_tls(mut self, use_tls: bool) -> Self { ... }
    fn timeout(mut self, timeout: u64) -> Self { ... }
    fn build(self) -> ServerConfig { ... }
}

调用:

let config = ServerConfigBuilder::new()
    .host("localhost")
    .port(8080)
    .use_tls(true)
    .timeout(30)
    .build();

特点:

  • 方法链清晰表达构造过程
  • 支持默认值和可选字段
  • 调用者无需了解完整内部初始化逻辑

6.2 和传统 OOP 写法相比有什么不同

  1. Rust 不依赖类继承体系,也不需要 Director 角色,调用方可以直接链式调用 Builder。
  2. Rust 方法链通过所有权移动实现,每一步返回 self,保证构造过程安全。
  3. 默认值和可选字段可以用 OptionDefault trait 实现,不必写多个构造函数重载。
  4. 不依赖接口或虚函数,而是通过静态方法链完成组合。

6.3 Rust 中是否有更自然的替代写法

  • 对简单对象,可以直接用结构体初始化语法 { field1, field2, ..Default::default() }
  • 对少量字段组合,也可以用 Option + unwrap_or 或默认值代替 Builder
  • 对复杂对象或链式构造仍然推荐 Builder,尤其在 API 客户端、配置对象和任务初始化场景

7. Rust 中涉及的语言特性

1. struct + impl
2. 方法链(返回 Self)
3. Option 类型
4. Default trait
5. 所有权移动
6. 类型安全

这些特性分别解决的问题:

  • struct + impl:组织数据和行为
  • 方法链:安全组合构建步骤
  • Option + Default:处理可选字段和默认值
  • 所有权移动:确保 Builder 使用安全
  • 类型安全:编译期检查必填字段是否初始化

8. 性能与工程代价

  • 构建者模式本身开销极小,只是组合 struct 实例和方法链
  • 对大量临时 Builder 对象,可能会产生栈分配和轻量移动开销
  • 对复杂对象,方法链可以减少重复初始化代码,提高可读性和可维护性
  • Rust 静态分发和优化使得 Builder 通常不会带来额外性能负担

9. 典型应用场景

1. 配置对象初始化(如服务器配置、HTTP 请求)  
2. 数据库查询条件构建  
3. 任务或流程配置(如批量任务执行器)  
4. API 客户端初始化(可选参数较多)  
5. 测试数据构造

10. 和相似模式的区别

  • 原型模式:基于已有对象复制 → 构建者模式按步骤构造新对象
  • 工厂模式:创建对象 → Builder 强调逐步可配置、链式调用
  • 单例模式:保证唯一实例 → Builder 用于灵活构造不同实例

11. 使用该模式的优点

1. 构造复杂对象的逻辑清晰  
2. 可组合可选字段,链式表达构造过程  
3. 减少重复初始化代码  
4. 提升代码可读性和可维护性  
5. 静态类型检查保证构造过程安全

12. 使用该模式的代价

1. 增加 Builder 类型和方法数量  
2. 对小对象可能显得冗余  
3. 链式调用过长可能影响可读性  
4. 临时 Builder 对象存在轻量开销

13. 什么时候不应该使用

1. 对象很简单,可直接用结构体初始化  
2. 字段数量少,构造函数足够清晰  
3. 不需要链式调用或可选字段  
4. 仅创建少量对象,复杂 Builder 成本大于收益

14. 一个简单例子思路

场景: HTTP 请求对象构造

  • 请求对象包含 URL、method、headers、body、timeout、retry 等字段
  • 大部分字段有默认值,部分可选
  • 调用方按需设置字段

处理流程:

1. 创建 RequestBuilder::new()
2. 链式调用方法设置 URL、method、headers
3. 可选字段使用默认值或 set 方法
4. 调用 build() 返回 Request 对象

练习 Rust 特性:structimpl、方法链、Option、Default


15. 总结一句话

构建者模式的本质是:

将复杂对象的构造过程抽离出来,通过方法链按步骤设置字段,最终生成完整对象。在 Rust 中,结合 struct、Option、Default 和方法链即可自然实现。