建造者模式
一个有 20 个参数的构造函数
候选人小张在字节面试时,面试官翻到他的代码,问:"这个 User 类有多少个字段?"
小张说:"20 个。"
面试官:"构造函数有几个参数?"
小张:"...20 个。"
面试官沉默了三秒,说:"这 20 个参数,面试官怎么知道哪个是哪个?你自己三个月后还记得吗?"
小张的构造函数是这样的:
这就是建造者模式要解决的问题:让对象创建既可读又灵活。
一、核心思想
建造者模式把一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。
二、手写建造者🔴
2.1 标准写法
2.2 使用方式
对比构造函数调用:
2.3 为什么构造函数是私有的?
强制使用 Builder 的好处:
- 所有对象创建都经过同一个入口
- 可以统一加验证逻辑(在
build()方法中) - 可以在 Builder 中加默认值处理
【架构权衡】 构造函数私有化 + Builder 是构建不可变对象的最佳组合。不可变对象天然线程安全,没有同步开销,没有意外修改风险。但代价是每个类都要写一个对应的 Builder,代码量翻倍。
三、Lombok @Builder 偷懒利器🟡
3.1 一行注解搞定
Lombok 自动生成:
UserBuilder内部类User.builder()静态工厂方法build()方法- 所有
withXxx()链式调用方法
3.2 Lombok 的坑
Lombok 生成的 Builder 会把所有字段都设为可选(使用默认值)。但如果你想让某些字段必须设置,需要配合 @Builder.Default 或手动处理:
Lombok 的 @Builder 会生成一个无参构造函数(如果类中没有显式的构造函数)。但如果你手动加了一个有参构造函数,Lombok 就不会生成无参构造函数了。解决方法是用 @Builder 配合 @AllArgsConstructor 和 @NoArgsConstructor。
四、建造者模式的进阶用法🟡
4.1 参数校验
4.2 默认值与必填校验分离
4.3 建造者 + 继承
如果你的类需要被继承,Builder 也要继承:
这个模式叫 "沿链传递"(Simulated Self-Type),是 Effective Java Item 2 推荐的写法。
五、建造者 vs 其他创建模式
【面试官心理】 我问他建造者模式,最想看的是他有没有理解"为什么需要这个模式"。能说出"解决构造函数参数过多问题"的只是基本操作,能说出"建造者模式配合不可变对象"的才是真正理解的设计思路。如果他还能提到 Lombok @Builder,那是用过工具链的加分项。
六、生产避坑清单
6.1 可变 Builder 的陷阱
6.2 建造者的性能
6.3 什么时候不用建造者
:::tip 💡 经验法则:参数少于等于 4 个时,构造函数足够清晰。超过 4 个可选参数时,建造者模式开始体现价值。但超过 10 个参数?不用建造者就是在给自己挖坑。
七、面试总结
7.1 核心问题
- "建造者模式和构造函数比,有什么优势?" —— 必问。参数可读性、默认值处理、不可变性支持。
- "你用过 Lombok @Builder 吗?有没有踩过坑?" —— 实际用过的人会有感悟。
- "什么场景下你会选择建造者模式?" —— 核心是"参数过多 + 部分参数可选 + 需要不可变对象"。
- "建造者模式能解决什么问题?" —— 构造函数参数过多难以维护、参数顺序记不住、无法表达语义。