设计模式之构建者模式

图1

构建者模式说明

构建者模式,也称生成器模式,是一种创建型的设计模式。将一个复杂对象的具体创建过程与其表示进行分离,客户端只需要知道具体的构建者类型,而无需知道具体的构建过程;同时支持链式调用也是构建者模式的一个优点。

一个标准的构建者模式由Director(指挥者)abstractBuilder(抽象构建者)concreteBuilder(具体构建者)Product(产品)四个角色组成。

构建者模式的UML图

img

图中几种角色的说明:

  1. Director(指挥者): 指挥者的主要作用是控制对象创建的次序,这里主要为constroctor()的实现。由于具体的实现是由构建者完成的,所以,指挥者需要持有构建者的实例。
  2. AbstractBuilder(抽象构建者): 该抽象对象可以由抽象类或者接口来完成。主要是定义创建设置复杂对象各个部件的方法和提供一个返回复杂对象的方法。
  3. ConcreteBuilder(具体构建者): 主要是实现抽象构建者中的方法,因为是由其直接接触产品来进行各属性的设置,所以,需要持有具体产品的引用。
  4. Product(产品类): 就是需要创建的复杂对象,而复杂对象的各个部件实际上就是其各个属性。
  5. client(场景类): 测试类,在此对象中我们需要创建指挥者,并为指挥者指定具体的构造器。

构建者模式的示例

通过代码实现一个标准的构建者模式的示例,这个例子通过构建一台小汽车的方式来对构建者模式进行说明。

Product类的实现

public class Car {
private String wheel; //轮子
private String circle; //方向盘
private String engine; //发动机
}

这里的产品为一台汽车的构造。假设这个汽车主要由轮子、方向盘、发动机三部分组成。

AbstractBuilder抽象构建者的实现

public abstract class AbstractBuilder {
    protected abstract void buildWheel();

    protected abstract void buildCircle();

    protected abstract void buildEngine();

    protected abstract Car build();
}

这里主要是定义了相关部件的创建方法及产品对象的创建方法。由具体的实现类去实现相应的方法。

ConcreteBuilder具体构建者的实现

public class ConcreteBuilder extends AbstractBuilder {
    private Car car = new Car();

    @Override
    protected void buildWheel() {
        car.setWheel("benz wheel");
    }

    @Override
    protected void buildCircle() {
        car.setCircle("benz circle");
    }

    @Override
    protected void buildEngine() {
        car.setEngine("benz engine");
    }

    @Override
    protected Car build() {
        return car;
    }
}

具体构建者通过成员变量的方式持有产品对象的实例。并实现了相应的构建方法来对产品的各部件进行构建,并返回了该构建的产品对象。

Director(指挥者)的实现

public class Director {
    private AbstractBuilder builder;

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

    public Car constructor() {
        builder.buildWheel();
        builder.buildCircle();
        builder.buildEngine();
        return builder.build();
    }
}

指挥者通过构造函数注入的方式,将具体的构建者传递了进来;然后,通过constructor()方法来指定各部分的创建次序,构建完成后,直接返回已经构建好了的对象。

Client(场景类)的实现

public class Client {
    public static void main(String[] args) {
        AbstractBuilder builder = new ConcreteBuilder();
        Director director = new Director(builder);
        director.constructor();
    }
}

client(f场景类)主要指的就是使用者,使用者只需要创建相应的Director对象,并传入具体的构建者,调用相应的Director方法即可完成复杂对象的创建。

到这里,一个标准的构建者模式的示例就编写完成了。大家有没有觉得哪儿有点多余?或者说和平时见到的构建者有什么不同?实际上,这里确实是有一点繁琐,完全可以把指挥者所做的事情,交由抽象构建者来完成。这里和模板方法结合了。在抽象构建者中定义了算法的骨架。

优化后的AbstractBuilder

public abstract class AbstractBuilder {
    protected Car car = new Car();

    protected abstract void buildWheel();

    protected abstract void buildCircle();

    protected abstract void buildEngine();

    protected Car build() {
        buildWheel();
        buildCircle();
        buildEngine();
        return car;
    }
}

这里主要做了两点优化:

  1. 将产品对象由子类提取到了父类
  2. 定义了算法的骨架,在build中定义了产品的创建顺序并返回了产品。

改造后的代码比之前的标准的格式精简了不少,可是总感觉和平时见的构建者模式还是有些许不同。嗯!实际上我们一般在使用构建者模式时,一般是在复杂产品的内部创建一个内部类,然后,设置相应的属性,最后提供一个build方法来创建具体的产品对象。

也就是说我们可以将生成器模式的代码写在同一个类里面。呵呵,是不是更精简了。

终极构建者模式

public class Car {
    private String wheel;  //轮子
    private String circle;  //方向盘
    private String engine;  //发动机

    public Car(Builder builder) {
        wheel = builder.wheel;
        circle = builder.circle;
        engine = builder.engine;
    }


    public String getWheel() {
        return wheel;
    }

    public void setWheel(String wheel) {
        this.wheel = wheel;
    }

    public String getCircle() {
        return circle;
    }

    public void setCircle(String circle) {
        this.circle = circle;
    }

    public String getEngine() {
        return engine;
    }

    public void setEngine(String engine) {
        this.engine = engine;
    }

    public static class Builder {
        private String wheel;  //轮子
        private String circle;  //方向盘
        private String engine;  //发动机

        public Builder setWheel(String wheel) {
            this.wheel = wheel;
            return this;
        }

        public Builder setCircle(String circle) {
            this.circle = circle;
            return this;
        }

        public Builder setEngine(String engine) {
            this.engine = engine;
            return this;
        }

        public Car build() {
            return new Car(this);
        }
    }
}

场景类的调用方式:

Car.Builder builder = new Car.Builder();
Car car = builder.setCircle("benz circle")
        .setWheel("benz wheel")
        .setEngine("benz engine")
        .build();

上面就是调用终极构建者的代码,通过链式调用的方式代码非常的简洁。

构建者模式的总结

优点

  1. 构建者模式将复杂对象的创建与表示分离,客户端不需要知道复杂对象的组成细节,使得相同的构造过程可以创建出不同的产品对象。
  2. 具体的构建者相互独立,在新增构建者或者替换构建者都不会对代码造成影响,易于扩展,符合开闭原则。

缺点

  1. 构建者模式创建的产品对象特性大多相似,如果产品之前差异较大,则不适合使用构建者模式。

应用场景

  1. 需要生成的产品内部相对复杂,该对象由多个属性组成。
  2. 需要生成的产品相互关联,创建产品时有一定的顺序
  3. 将对象的创建过程与对象的表示分离