关于 gof-builder
介绍 GoF Builder 模式的技能,面向需要组装复杂对象的开发者。内容涵盖流式构建器和类型安全 DSL,并说明何时应优先使用命名参数或默认值。
主要功能
- 01通过分步构造组装对象
- 02支持流式构建器形式
- 03介绍类型安全 DSL 构建器
- 04说明 Builder 与 Factory 的区别
- 05强调构建时验证对象
适用场景
- 01构造函数包含许多可选参数
- 02对象需按多个步骤完成组装
- 03希望调用代码呈现清晰的组装流程
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ yonatankarp/ software-design-skills --skill gof-builder安装后在 Claude Code 中输入/gof-builder确认已加载。
详细介绍
一句话总结
将复杂对象的构造与其表示分离,让同一构造流程能够生成不同结果,并用流畅、易读的组装方式取代“伸缩构造函数”。
何时使用此技能
- 对象有很多构造函数参数(约 4 个以上),其中有几个是可选的。
- 构造过程分多个步骤进行(制作汉堡,然后添加配料,再包装),且步骤可能有所不同。
- 你希望调用代码读起来像菜谱,而不是费力应对构造函数签名。
- Kotlin DSL 惯用写法——
html { head { … } body { … } }——就是一种构建器。
何时不使用此技能
- 构造函数只接受 1–3 个参数,直接调用清晰易读。
- 该语言已经提供了更好的工具——Kotlin 的命名参数 + 默认参数值在大多数情况下无需 Builder。只有当构造确实需要分阶段进行时(需要中间验证或类型安全的步骤顺序),才使用 Builder。
- 你要构建的是单个不可变值对象——使用带命名参数的
data class几乎总是足够的。
何时选择 Builder 而不是 Factory(gof-factory)
- Factory 隐藏了要实例化哪种具体类型。
- Builder 隐藏了如何组装一个类型已知的实例。
二者可以组合使用:Factory 可以返回 Builder;Builder 也可以使用 Factory 构建子部件。
核心内容
两种常见形式:
流式构建器。 Builder 类通过链式 setter 方法累积状态,并以 build() 结束:
Burger.builder()
.bun(Brioche)
.patty(Beef)
.topping(Cheese).topping(Bacon)
.build()
每个 setter 都返回 this(或 Builder),以便链式调用。build() 会进行验证并返回完成后的对象。目标类型应使用私有构造函数,以确保调用方必须通过构建器创建对象。
类型安全的 DSL 构建器(Kotlin 惯用写法,但这个概念更早就已存在)。函数接受一个带接收者的 lambda;在 lambda 内部,可以直接使用构建器的方法。Kotlin 标准库中的 buildString { append("hello"); append(" world") } 是最简单的例子。HTML 风格的构建器则更进一步。
一个常见错误是为实际上并不需要 Builder 的对象实现 Builder——只有当构造复杂到单次构造函数调用会掩盖意图时,Builder 才有意义。
决策启发
- 统计构造函数参数的数量。少于约 4 个时,Builder 属于过度设计——使用命名参数。
- 查看是否有带合理默认值的可选参数。如果大多数参数都有默认值,命名参数 + 默认值比 Builder 更易读。
- 如果构造需要多个阶段,且第 N 阶段依赖第 N−1 阶段,那么 Builder(尤其是基于类型状态的 Builder)就值得采用。
- 如果目标对象应当不可变,
build()必须生成经过完整验证的值,并且构建器本身应被丢弃。
反模式
- 明明使用命名参数就够了,却使用 Builder——徒增形式,没有收益。
- 允许
build()返回无效对象的构建器——这违背了安全性目的。 - “Builder”类持有对已构建对象的可变引用,并在
build()之后继续修改它。 - 在多个线程之间共享同一个 Builder 实例——Builder 通常有状态,并不安全。
另请参阅
gof-factory— Builder 隐藏组装过程;Factory 隐藏类型选择。二者可以组合使用。gof-prototype— 当现有实例是更便捷的起点时,可将其作为 Builder 的替代方案。gof-kotlin-idioms— 命名参数 + 默认值在大多数 Kotlin 代码中可以取代 Builder;类型安全的 Builder DSL 是主要例外。
参考资料
- Design Patterns(GoF,1994),第 3 章——Builder。(未收录于《HFDP》第 2 版;该书仅略有涉及。)
- Kotlin Design Patterns and Best Practices(Alexey Soshin),第 2 章——Builder,并明确与 Kotlin 的命名参数进行比较。
评论
支持 Markdown