1、定义

将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示。建造者模式是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。

2、模式结构

建造者(Builder)模式 - 图1

构造者模式由四部分组成:

  • Builder(抽象构造者):给出一个抽象接口,以规范产品对象的各个组成成分的建造。一般而言,此接口独立于应用程序的商业逻辑。模式中直接创建产品对象的是具体建造者角色。具体建造者类必须实现这个接口所要求的两个方法:一种是建造方法,另一种是返回结构方法。一般来说,产品所包含的零件数目与建造方法的数目相符。换言之,有多少零件,就有多个相应的建造方法。
  • ConcreteBuilder(具体构造者):与应用程序紧密相关的一些类,它们在应用程序调用下创建产品的实例。这个角色要完成的任务包括:实现抽象创造者所声明的接口,给出一步一步地完成创建产品实例的操作;在建造过程完成后,提供产品的实例。
  • Director(导演者):负责调用具体建造者按照顺序建造产品。导演者只负责调度,真正执行的是具体建造者角色。
  • Product(产品):产品便是建造中的复杂对象。

3、实例

3.1 房子(Product)

  1. public class House {
  2. private String basis;
  3. private String wall;
  4. private String roof;
  5. // toString、getter方法和setter方法
  6. }

3.2 抽象构造者类(Builder)

  1. public abstract class HouseBuilder {
  2. public abstract void buildBasis();
  3. public abstract void buildWall();
  4. public abstract void buildRoof();
  5. public abstract House getHouse();
  6. }

3.3 具体构造者类(ConcreteBuilder)

  1. public class HighBuilding extends HouseBuilder{
  2. private House house = new House();
  3. @Override
  4. public void buildBasic() {
  5. house.setBasic("高楼打地基100m深");
  6. }
  7. @Override
  8. public void buildWall() {
  9. house.setWall("高楼砌墙30cm宽");
  10. }
  11. @Override
  12. public void buildRoof() {
  13. house.setRoof("高楼使用透明屋顶");
  14. }
  15. @Override
  16. public House getHouse(){
  17. return house;
  18. }
  19. }

3.4 导演者类(Director)

  1. public class HouseDirector {
  2. public void buildHouse(HouseBuilder houseBuilder) {
  3. houseBuilder.buildBasis();
  4. houseBuilder.buildWall();
  5. houseBuilder.buildRoof();
  6. }
  7. }

3.5 客户端调用

  1. public class Client {
  2. public static void main(String[] args) {
  3. HouseBuilder highBuilding = new HighBuilding();
  4. HouseDirector houseDirector = new HouseDirector();
  5. houseDirector.buildHouse(highBuilding);
  6. System.out.println(highBuilding.getHouse().toString());
  7. }
  8. }

4、适用场景

  • 需要生成的产品对象有复杂的内部结构,这些产品对象通常包含多个成员属性。
  • 需要生成的产品对象的属性相互依赖,需要指定其生成顺序。
  • 对象的创建过程独立于创建该对象的类。在建造者模式中引入了指挥者类,将创建过程封装在指挥着类,而不在建造类中。
  • 隔离复杂对象的创建和使用,并使得相同的创建过程可以创建不同的产品。

5、在JDK的应用

StringBuilder的部分源码:

建造者(Builder)模式 - 图2

  • Appendable接口定义了多个append方法(抽象方法),即Appendable为抽象建造者。
  • AbstractStringBuilder实现了Appendable接口方法,这里的AbstractStringBuilder已经是建造者,只是不能实例化。
  • StringBuilder即充当了指挥者角色,同时充当了具体的建造者,建造方法的实现是由AbstractStringBuilder完成,而StringBuilder继承了AbstractStringBuilder.

6、优缺点

6.1 优点
  • 客户端(应用程序)不必知道产品内部组成的细节,将产品本身与产品的创建过程解耦,使得相同的创建过程可以创建不同的产品对象。
  • 每一个具体建造者都相对独立,而与其他的具体建造者无关,因此可以很方便地替换具体建造者或增加新的具体建造者,用户使用不同的具体建造者即可得到不同的产品对象。
  • 可以更加精细地控制产品的创建过程。将复杂产品的创建步骤分解在不同的方法中,使得创建过程更加清晰,也更方便使用程序来控制创建过程。
    *增加新的具体建造者无须修改原有类库的代码,指挥者类针对抽象建造者类编程,系统扩展方便,符合“开闭原则”。

6.2 缺点
  • 建造者模式所创建的产品一般具有较多的共同点,其组成部分相似,如果产品之间的差异性很大,则不适合使用建造者模式,因此使用范围受到一定的限制。
  • 如果产品的内部变化复杂,可能会导致需要定义很大具体建造者类来实现这种变化,导致系统变得很庞大,因此在这种情况下,要考虑是否选择建造者模式。

7、建造者模式和抽象工厂的区别

  • 建造者模式返回一个组装好的完整产品,而抽象工厂模式返回一系列相关的产品,这些产品位于不同的产品等级结构,构成了一个产品族。
  • 在抽象工厂模式中,客户端实例化工厂类,然后调用工厂方法获取所需产品对象;而在建造者模式中,客户端可以不直接调用建造者的相关方法,而是通过指挥者类来指导如何生成对象,包括对象的组装过程和建造步骤,它侧重于一步步构造一个复杂对象,返回一个完整的对象。
  • 如果将抽象工厂模式看出汽车配件生产工厂,生产一个产品族的产品,那么建造者模式就是一个汽车组装工厂,那么对部件的组装可以返回一辆完整的汽车。