c#中最实用的builder实现是链式withxxx()方法+私有字段+build()终态校验;所有with方法返回this、字段私有、校验和副作用仅在build()中执行,并设_isbuilt标志防止重复调用。

直接用链式 WithXxx() 方法 + 私有字段 + Build() 终态校验,是 C# 里最实用、最不容易翻车的 Builder 实现方式。别一上来就搞抽象类和 Director,90% 的业务场景根本用不上。
Builder 类必须返回 this 才能链式调用
链式调用不是语法糖,是 Builder 可读性的基础。如果每个设置方法返回 void 或新建实例,就失去“一口气配完”的表达力。
-
WithSize()、WithCheese()等方法必须返回this,且不能 new 新 Builder 实例 - 所有字段声明为
private,不暴露 setter,防止外部绕过 Builder 直接改状态 - 不要在
WithXxx()里做校验或副作用(比如连接数据库),这些逻辑属于Build()阶段
Build() 是唯一出口,必须做终态校验
构造逻辑的完整性、合法性、不可变性,全靠 Build() 把关。分散校验等于没校验。
- 检查必填字段是否已设置,例如
if (_toppings.Count == 0) throw new InvalidOperationException("At least one topping is required.") - 加
private bool _isBuilt标志,防止重复调用Build()导致状态污染 - 返回对象时尽量用只读封装,比如
_toppings.AsReadOnly()或IReadOnlyList<string></string>,切断外部修改通路 - 如果 Product 类本身要不可变,就用私有构造函数 + 公共只读属性,所有值由
Build()一次性传入
别急着抽象出 IBuilder 和 Director
抽象接口和指挥者模式只在“多个 Builder 复用同一构建流程”时才有价值。多数项目里,一个 Builder 对应一个 Product 就够了。
- 过早提取
abstract class PizzaBuilder或interface IBuilder<t></t>,反而让调用方多一层转换,还容易把 Product 构造细节泄露进 Builder -
Director类(比如控制“先加面团再加料”顺序)只在算法稳定、表示多变的场景才需要,比如配置中心生成不同环境的ConnectionSettings - 真正该警惕的是:Builder 里出现
new Pizza()或直接给 Product 字段赋值——这说明你把创建逻辑又塞回去了,Builder 只剩个壳
最容易被忽略的一点:Build() 不只是“造对象”,它还是“封口”动作。一旦调用,Builder 就该进入只读状态;否则多人协作时,有人顺手又调了一次 WithTopping(),再 Build(),结果就是脏数据或异常行为。










