设计模式创建者模式生成器 Builder
解决复杂对象创建以及装配问题
GOF 中描述的 Builder 模式
UML 图中,客户端(也就是你)使用 Director(导演)来解决对象创建工作
Director 在这个过程中,安排 Builder 做一些预先设计好的对象创建流程
- 实现 Builder 后,可以水平扩展无数个 Builder(图中的 Concrete Builder1 和 Concrete Builder2,你可以自己继续扩展3,4,5,6,7...),这个就是 Builder 模式的作用之 1
- 然后 Client 使用 Director 来创建 Product 对象,创建对象的过程已经被预先设计好了,使用构造器注入 ConcreteBuilder。
- 最后在需要切换不同的 Builder 的时候,直接 new 一个实体 Builder 放进 Director 中就行(实践中你可能会需要依赖注入解决这个问题),我们在第二步写的代码就不需要修改了,这个是作用之 2
每当因为业务需要一个新的 Product,就通过实现 Builder 接口建立一个新的 ConcreteBuilder,然后丢给 Director(Builder builder)
这个模式的好处就是写在 Director 中的创建对象代码,在你添加新的 Builder 的时候,不需要去修改 Director 中的代码(面向扩展开放,面向修改封闭,开闭原则)
Director 其实是 Builder 模式最核心的地方(它使用了接口提供的泛型编程,减少样板代码,复用了构建对象的通用过程),对所有继承了 Builder 的实体类,统一按照某种预定义的顺序进行对象构建,要注意的是 Director 可以保存多种不同的 Product 的创建流程,比如先上漆后烘干流程,或者先烘干后上漆流程
结合英语语境来理解
Director 在英语中表示导演
,负责人
, 管理者
也就是安排某人做某事的这种角色
在 Builder 模式中,Director 就是安排 Builder 去做某件事
就像导演需要一个龙套演员,对龙套演员的要求是能做出装死动作,导演不需要关系具体是谁在演这个角色,剧组直接塞一个随机抽选的龙套演员过来就行,剧本还是一样的走,我们不因为演员的不同而去修改剧本,只是在创建者模式中,行为是创建对象,不是装死
结合 Laravel 源代码来理解
可以参考 Laravel Query Builder 的设计:
- Client 也就是你在编写代码的地方
- Director 也就是
Db::table()
中的 Db - ConcreteBuilder 也就是
Db::table('table_name')
的 table_name - 至于 BuildPartA,BuildPartB,BuildPartC 嘛
- 就是
Db::table('table_name')->where()->orderBy()->.....
- 中的链式调用方法
- 至于 Product 就是返回的数据
Laravel 中的 QueryBuilder 实际上把 Director 干掉了,因为通常情况下我们是在控制器中直接写 Builder 查询对象结果集,极少会去封装为 Service,当然你也可以把 Model 或者你自己创建的 Service 叫做 Director,将调用链语句打包封装为一个方法,这个实际上也是 Builder 模式。