3.2-Builder-生成器模式-创建型模式
Builder
用途
将复杂对象的构建和表示分离,使得同样的构建过程可以创建不同的表示。
示例
考虑应用场景:将 RTF 文档转换为其他多种文本格式,对于任意结构的文档,可能的转换数目是无限的
RTFReader:分析文档,每次遇到一个标记时发送请求调用 TextConverter 转换该标记。
TextConverter 对象负责进行数据转换以及用特定格式表示该标记,其子类对不同转换和不同格式进行特殊处理。
解释:Builder 模式描述了所有这些关系。
- 每一个转换器类在该模式中被称为生成器(builder),而阅读器则称为导向器(director)
- Builder 模式将分析文本格式的算法(即 RTF 文档的语法分析程序)与描述怎样创建和表示一个转换后格式的算法分离开来。这使我们可以复用 RTFReader 的语法分析算法,根据 RTF 文档创建不同的文本表示——仅需使用不同的 TextConverter 的子类配置该 RTFReader 即可。

适用情形
- 当创建复杂对象的算法应该独立于该对象的组成部分以及它们的装配方式时。
- 当构造过程必须允许被构造的对象有不同的表示时。
结构

- Builder:创建 Product 的抽象接口
- ConcreteBuilder:(ASCIIConverter、TeXConverter、 TextWidgetConverter)
- 构造和装配产品的各个部件
- 定义和跟踪自己创建的表示
- 提供检索产品的接口(例如,GetASCIIText 和 GetTextWidget)
- Director:(RTFReader)构造使用 builder 接口的对象
- Product(ASCIIText、TeXText、TextWidget)
- 被构建的复杂对象,具体生成器创建该产品的内部表示并定义装配过程
- 包含定义组件部件的类,以及将这些部件装配成最终产品的接口
协作过程如下:
- 客户创建 Director 对象,并用它所想要的 Builder 对象进行配置。
- 一旦生成了产品部件,导向器就会通知生成器。
- 生成器处理导向器的请求,并将部件添加到该产品中。
- 客户从生成器中获取最终产品。

优缺点
- 可以改变一个产品的内部表示:因为产品是通过抽象接口构造的,你在改变该产品的内部表示时所要做的只是定义一个新的生成器。
- 将构造代码和表示代码分开:Builder 模式通过封装一个复杂对象的创建和表示方式提高了对象的模块性。构造代码只写一次,不同的 Director 可以反复复用构造代码在同一套部件集合上创建不同的表示
- 可以精细控制构造过程:它是在导向器的控制下一步一步构造产品的。仅当该产品完成时导向器才从生成器中取回它。
实现
通常有一个抽象的 Builder 类为导向器可能要求创建的每一个构件定义一个操作(默认什么都不做)。 一个 ConcreteBuilder 类对它有兴趣创建的构件重定义这些操作。
注意事项:
- 关于装配和构造接口:
- Builder 类接口必须足够普遍,以便为各种类型的具体生成器构造产品。
- 有时需要访问已构造的部件:例如语法分析树自下而上构建,此时需要由生成器将子结点(已生成的产品)返回导向器,导向器将其回传给生成器构建父结点
- Builder 中使用空方法而非纯虚函数:这使得子类只需要重定义他们感兴趣的操作
- 产品没有抽象基类:具体生成器生产的产品的差异通常很大,例如 ASCIIText 和 TextWidget 两者不太可能有公共接口
迷宫案例

MazeBuilder(抽象 Builder):提供 BuildRoom,BuildDoor、BuildMaze 方法,和最终返回 Maze 的 GetMaze 方法
- StandardMazeBuilder(具象 Builder):实现上述的具体方法 MazeGame(Director):调用 MazeBuilder 中的方法,具体生成迷宫
