设计模式创建者模式 Builder

发布时间 2023-10-22 19:57:20作者: 我听不见

解决复杂对象创建以及装配问题

GOF 中描述的 Builder 模式

UML 图中,客户端(也就是你)使用 Director(导演)来解决对象创建工作。
Director 在这个过程中,安排 Builder 做一些预先设计好的对象创建流程。

  1. 实现 Builder 后,可以水平扩展无数个 Builder(图中的 Concrete Builder1 和 Concrete Builder2,你可以自己继续扩展3,4,5,6,7...),这个就是 Builder 模式的作用之 1
  2. 然后 Client 通过直接使用实现了 Builder 的对象,针对接口进行代码编写
  3. 最后在需要切换不同的 Builder 的时候,直接 new 一个实体 Builder 放进 Director 中就行(实践中你可能会需要依赖注入解决这个问题),我们在第二步写的代码就不需要修改了,这个是作用之 2

每当因为业务需要一个新的 Product,就通过实现 Builder 接口建立一个新的 ConcreteBuilder,然后丢给 Director(Builder builder)

Director 其实是 Builder 模式最核心的地方(它使用了接口提供的泛型编程,解决通用处理步骤,减少样板代码,复用了构建对象的通用过程),对所有继承了 Builder 的实体类,统一按照某种顺序进行构建,避免了每次的重复构建对象代码,要注意的是 Director 可以保存多种不同的 Product 的创建流程,比如先上漆后烘干流程,或者先烘干后上漆流程。

结合英语语境来理解

Director 在英语中表示导演负责人, 管理者
也就是安排某人做某事的这种角色
在 Builder 模式中,Director 就是安排 Builder 去做某件事。
就像导演需要一个龙套演员,对龙套演员的要求是能做出装死动作,导演不需要关系具体是谁在演这个角色,剧组直接塞一个随机抽选的龙套演员过来就行,剧本还是一样的走,我们不因为演员的不同而去修改剧本。

结合 Laravel 源代码来理解

可以参考 Laravel Query Builder 的设计:

  1. Client 也就是你在编写代码的地方
  2. Director 也就是 Db::table() 中的 Db
  3. ConcreteBuilder 也就是 Db::table('table_name') 的 table_name
  4. 至于 BuildPartA,BuildPartB,BuildPartC 嘛
  5. 就是 Db::table('table_name')->where()->orderBy()->.....
  6. 中的链式调用方法,这和 jQuery 的链式调用是一样的,都是通过返回 this来构造一个组装过程
  7. 至于 Product 就是你要的数据

Laravel 中的 QueryBuilder 实际上把 Director 干掉了,因为通常情况下我们是在控制器中直接写 Builder 查询对象结果集,极少会去封装为 Service,当然你也可以把 Model 或者你自己创建的 Service 叫做 Director,将调用链语句打包封装为一个方法,这个实际上也是 Builder 模式,其实PHP中不需要这么多模式,因为灵活性,很多模式都是不必要的,就像在 Lisp 中根本不知模式为何物,高阶函数解决一大堆的灵活扩展问题。