第十三章 建造者模式(Builder)

建造者模式的定义与特点

  1. 定义:将一个复杂对象的构建和它的表示分离,使得同样的构建过程可以创建出不同的表示。
  2. 特点:建造者模式可以将一个产品的内部表象和生产过程相分离,从而可以通过一个建造过程而创建出不同内部表象的产品对象。它是将一个复杂的对象分解为多个简单的对象,然后一步一步构建而成。它将变与不变相分离,即产品的组成部分是不变的,但每一部分是可以灵活选择的。

如果使用建造者模式,那么用户就只需要指定建造的类型就可以得到他们,而具体的建造细节和过程就不需要知道了。

建造者(Builder)模式和工厂模式的关注点不同:建造者模式注重零部件的组装过程,而工厂方法模式更注重零部件的创建过程,但两者可以结合使用。

建造者模式的结构与实现

  1. 模式的结构
    建造者(Builder)模式的主要角色如下。
  • 产品角色(Product):它是包含多个组成部件的复杂对象,由具体建造者来创建其各个子部件。
  • 抽象建造者(Builder):它是一个包含创建产品各个子部件的抽象方法的接口,通常还包含一个返回复杂产品的方法 getResult()。
  • 具体建造者(Concrete Builder):实现 Builder 接口,完成复杂产品的各个部件的具体创建方法。
  • 指挥者(Director):它调用建造者对象中的部件构造与装配方法完成复杂对象的创建,在指挥者中不涉及具体产品的信息。

其结构如图所示:

image

  1. 模式的实现

Product:

public class Product {
    public String partA;
    public String partB;
    public String partC;

    public void setPartA(String partA) {
        this.partA = partA;
    }

    public void setPartB(String partB) {
        this.partB = partB;
    }

    public void setPartC(String partC) {
        this.partC = partC;
    }

    public void show() {
        System.out.println("该产品由" + partA + "," + partB + "," + partC + "组成");
    }
}

Builder:

public abstract class Builder {

    public abstract void buildPartA();

    public abstract void buildPartB();

    public abstract void buildPartC();

    public abstract Product getResult();
}

ConcreteBuilder1:

public class ConcreteBuilder1 extends Builder {

    private Product product;

    public ConcreteBuilder1() {
        product = new Product();
    }

    public void buildPartA() {
        product.setPartA("构建组件A");
    }

    public void buildPartB() {
        product.setPartB("构建组件B");
    }

    public void buildPartC() {
        product.setPartC("构建组件C");
    }

    public Product getResult() {
        return product;
    }
}

ConcreteBuilder2:

public class ConcreteBuilder2 extends Builder {

    private Product product;

    public ConcreteBuilder2() {
        product = new Product();
    }

    public void buildPartA() {
        product.setPartA("构建组件AA");
    }

    public void buildPartB() {
        product.setPartB("构建组件BB");
    }

    public void buildPartC() {
        product.setPartC("构建组件CC");
    }

    public Product getResult() {
        return product;
    }
}

Director:

public class Director {

    private Builder builder;

    public Director(Builder builder) {
        this.builder = builder;
    }

    /**
     * 创建Product实例
     *
     * @return
     */
    public Product construct() {
        this.builder.buildPartA();
        this.builder.buildPartB();
        this.builder.buildPartC();

        return this.builder.getResult();
    }
}

测试类:

public class BuilderTest {

    public static void main(String[] args) {
        Builder builder1 = new ConcreteBuilder1();

        Director director1 = new Director(builder1);

        Product product1 = director1.construct();

        product1.show();

        Builder builder2 = new ConcreteBuilder2();

        Director director2 = new Director(builder2);

        Product product2 = director2.construct();

        product2.show();
    }
}

测试结果:

该产品由构建组件A,构建组件B,构建组件C组成
该产品由构建组件AA,构建组件BB,构建组件CC组成

Process finished with exit code 0

Builder是抽象类,定义了构建各个组件的方法,由子类去实现具体的构建方法。在Director类中调用具体实现类ConcreteBuilder的各个构建方法去组装Product的实例。

建造模式还有另一种写法,将Director省去,在客户端调用各个组件的构造方法,由用户去决定构建产品的各个组件的细节,也就是说将Director的权力移交给了调用方。

第二种方式的建造者类:

public abstract class Builder2 {

    public abstract Builder2 buildPartA(String message);

    public abstract Builder2 buildPartB(String message);

    public abstract Builder2 buildPartC(String message);

    public abstract Product build();
}

和第一种方式的区别就是各个方法的返回值类型为建造者,并且组件的细节是通过参数传进去的。

具体的建造者实现类:

public class ConcreteBuilder3 extends Builder2 {

    private Product product;

    public ConcreteBuilder3() {
        product = new Product();
    }

    public Builder2 buildPartA(String message) {
        product.setPartA(message);
        return this;
    }

    public Builder2 buildPartB(String message) {
        product.setPartB(message);
        return this;
    }

    public Builder2 buildPartC(String message) {
        product.setPartC(message);
        return this;
    }

    public Product build() {
        return product;
    }
}

测试类:

ublic class Builder2Test {

    public static void main(String[] args) {
        Builder2 builder2 = new ConcreteBuilder3();

        Product product = builder2.buildPartA("A组件").buildPartB("B组件").buildPartC("C组件").build();

        product.show();
    }
}

测试结果:

该产品由A组件,B组件,C组件组成

Process finished with exit code 0

这种方式使用更加灵活,可以根据用户需求自由定义更改内容。但是也违背了用户不需要知道构建细节的定义。

模式的应用场景

建造者(Builder)模式创建的是复杂对象,其产品的各个部分经常面临着剧烈的变化,但将它们组合在一起的算法却相对稳定,所以它通常在以下场合使用。

  • 创建的对象较复杂,由多个部件构成,各部件面临着复杂的变化,但构件间的建造顺序是稳定的。
  • 创建复杂对象的算法独立于该对象的组成部分以及它们的装配方式,即产品的构建过程和最终的表示是独立的。

posted on 2020-04-19 23:14  liuxiany  阅读(120)  评论(0编辑  收藏  举报

导航