Java设计模式 —— 建造者模式

8 建造者模式

8.1 建造者模式概述

Builder Pattern:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。

建造者模式可以将部件本身和它们的组装过程分开,关注如何一步一步地创建一个包含多个组成部分的复杂对象,用户只需指定复杂对象的类型即可得到该对象,而无须知道其内部的具体构造细节。

建造者模式结构图如下:

8.2 建造者模式实现

8.2.1 抽象建造者类

public abstract class Builder {
  protected Product product = new Product();
  
  public abstract void buildPartA();
  public abstract void buildPartB();
  public abstract void buildPartC();
  
  // 返回产品对象
  public Product getProduct() {
    return product;
  }
}

8.2.2 具体建造者类

public class ConcreteBuilder extends Builder {
  public void buildPartA(PartA partA) {
    product.setPartA(partA);
  }
  
  public void buildPartB(PartB partB) {
    product.setPartB(partB);
  }
  
  public void buildPartC(PartC partC) {
    product.setPartB(partC);
  }
}

8.2.3 具体产品类

public class Product {
  private PartA partA;
  private PartB partB;
  private PartC partC;
  
  /**
   * get and set methods
   */
}

8.2.4 指挥者类

引入该类主要有两个作用:

  • 隔离了客户端与创建过程
  • 控制产品对象的创建过程
public class Director {
  private Builder builder;
  
  public Director(Builder builder) {
    this.builder = builder;
  }
  
  public void setBuilder(Builder builder) {
    this.builder = builder;
  }
  
  public Product construct() {
    builder.buildPartA();
    builder.buildPartB();
    builder.buildPartC();
    return builder.getProduct();
  }
}

8.2.5 客户端调用

对于客户端而言,只需要关注具体建造者的类型,无须关心产品对象的具体创建过程。

public class Client {
  Builder builder = new ConcreteBuilder();
  Director director = new Director(builder);
  Product product = director.construct();
}

8.3 指挥者类的变化形式

指挥者类是建造者模式的重要组成部分,简单的 Director 类用于指导具体创建如何创建产品,它按一定顺序调用 Builder 中的各个方法,控制先后顺序,并向客户端返回一个完整的产品对象。

8.3.1 省略指挥者类

为了简化系统结构,某些情况下可以将指挥者类和抽象建造者类进行合并,在 Builder 中提供构建复杂产品对象的 construct() 方法。由于 Builder 通常为抽象类,无法直接实例化,因此可以将 construct() 方法定义为静态方法,以便客户端可以直接调用。

public abstract class Builder {
  protected static Product product = new Product();
  
  public abstract void buildPartA();
  public abstract void buildPartB();
  public abstract void buildPartC();
  
  // 返回产品对象
  public static Product construct(Builder builder) {
    builder.buildPartA();
    builder.buildPartB();
    builder.buildPartC();
    
    return product;
  }
}


// 客户端调用
public class Client {
  Builder builder = new ConcreteBuilder();
  Product product = Builder.construct(builder);
}

由于静态变量是被所有实例所共享的,在内存中只有一个副本,因此上述方法只能创建一个 Product 对象。可以做如下改进:

public abstract class Builder {
  protected Product product = new Product();
  
  public abstract void buildPartA();
  public abstract void buildPartB();
  public abstract void buildPartC();
  
  // 返回产品对象
  public Product construct() {
    this.buildPartA();
    this.buildPartB();
    this.buildPartC();
    
    return product;
  }
}


// 客户端调用
Builder builder = new ConcreteBuilder();
Product product = builder.construct();

以上两种方法对 Director 类的省略方式都不影响系统的灵活性和扩展性,同时还简化了系统结构,但是加重了抽象建造者类的职责。如果 construct() 方法较为复杂,待构建产品组成较多,还是应该不省略指挥者类

8.3.2 钩子方法

建造者模式可以通过 Director 类更加精细的控制产品的创建过程,例如增加一类钩子方法来控制是需要对某个 buildPartX() 方法进行调用。

public abstract class Builder {
  protected Product product = new Product();
  
  public abstract void buildPartA();
  public abstract void buildPartB();
  public abstract void buildPartC();
  
  // 钩子方法, 子类可以覆盖该方法
  public boolean isBuildPartA() {
    return false;
  }
  
  public Product construct() {
    return product;
  }
}
public class Director {
  public Product construct(Builder builder) {
    if (builder.isBuildPartA()) {
      builder.buildPartA();
    }
    builder.buildPartB();
    builder.buildPartC();
    
    Product product = builder.construct();
    return product;
  }
}

8.4 建造者模式优/缺点

建造者模式优点主要如下:

  • 客户端无须知道产品内存的创建细节,将产品本身与创建过程解耦,使得相同的创建过程可以创建不同的产品对象
  • 每一个具体的建造者都相对独立,与其他具体建造者无关,可以很方便的增加或删除具体建造者
  • 更加精细地控制产品的创建过程,将复杂产品的创建步骤分解在不同的方法中

建造者模式缺点主要如下:

  • 如果产品的内部变化复杂,可能会导致需要定义很多具体的建造者类来实现这种变化,导致系统很庞大
posted @ 2022-10-03 18:29  ylyzty  阅读(22)  评论(0编辑  收藏  举报