Skip to content

建造者模式

亦称: 生成器模式、Builder

1. 简介

建造者模式是一种创建型设计模式, 使你能够分步骤创建复杂对象。该模式允许你使用相同的创建代码生成不同类型和形式的对象。

2. 模拟场景

Alt text 例如, 我们来思考如何创建一个 房屋House对象。建造一栋简单的房屋, 首先你需要建造四面墙和地板, 安装房门和一套窗户, 然后再建造一个屋顶。但是如果你想要一栋更宽敞更明亮的房屋, 还要有院子和其他设施(例如暖气、排水和供电设备), 那又该怎么办呢?
Alt text 最简单的方法是扩展 房屋基类, 然后创建一系列涵盖所有参数组合的子类。但最终你将面对相当数量的子类。任何新增的参数(例如门廊类型)都会让这个层次结构更加复杂。
另一种方法则无需生成子类。你可以在 房屋基类中创建一个包括所有可能参数的超级构造函数, 并用它来控制房屋对象。这种方法确实可以避免生成子类, 但它却会造成另外一个问题。 Alt text 通常情况下, 绝大部分的参数都没有使用, 这使得对于构造函数的调用十分不简洁。例如只有很少的房子有游泳池, 因此与游泳池相关的参数十之八九是毫无用处的。

3. 解决方案

建造者模式建议将对象构造代码从产品类中抽取出来, 并将其放在一个名为生成器的独立对象中。
该模式会将对象构造过程划分为一组步骤, 比如 build­Walls创建墙壁和 build­Door创建房门创建房门等。每次创建对象时, 你都需要通过生成器对象执行一系列步骤。重点在于你无需调用所有步骤, 而只需调用创建特定对象配置所需的那些步骤即可。
当你需要创建不同形式的产品时, 其中的一些构造步骤可能需要不同的实现。例如, 木屋的房门可能需要使用木头制造, 而城堡的房门则必须使用石头制造。
在这种情况下, 你可以创建多个不同的生成器, 用不同方式实现一组相同的创建步骤。然后你就可以在创建过程中使用这些生成器(例如按顺序调用多个构造步骤)来生成不同类型的对象。
Alt text 例如, 假设第一个建造者使用木头和玻璃制造房屋, 第二个建造者使用石头和钢铁, 而第三个建造者使用黄金和钻石。在调用同一组步骤后, 第一个建造者会给你一栋普通房屋, 第二个会给你一座小城堡, 而第三个则会给你一座宫殿。但是, 只有在调用构造步骤的客户端代码可以通过通用接口与建造者进行交互时, 这样的调用才能返回需要的房屋。
你可以进一步将用于创建产品的一系列生成器步骤调用抽取成为单独的主管类。主管类可定义创建步骤的执行顺序, 而生成器则提供这些步骤的实现。
Alt text 严格来说, 你的程序中并不一定需要主管类。客户端代码可直接以特定顺序调用创建步骤。不过, 主管类中非常适合放入各种例行构造流程, 以便在程序中反复使用。
此外, 对于客户端代码来说, 主管类完全隐藏了产品构造细节。客户端只需要将一个生成器与主管类关联, 然后使用主管类来构造产品, 就能从生成器处获得构造结果了。

总结

生成器是一种创建型设计模式, 使你能够分步骤创建复杂对象。
与其他创建型模式不同, 生成器不要求产品拥有通用接口。这使得用相同的创建过程生成不同的产品成为可能。

4. Java中的例子

  • java.lang.StringBuilder#append()(非同步)
  • java.lang.StringBuffer#append()(同步)
  • java.nio.ByteBuffer#put()(还有Char­Buffer、Short­Buffer、Int­Buffer、Long­Buffer、Float­Buffer和Double­Buffer)
  • javax.swing.GroupLayout.Group#addComponent()
  • java.lang.Appendable的所有实现