設計模式十: 生成器模式(Builder Pattern)

罪惡斯巴克發表於2018-10-19

簡介

生成器模式屬於建立型模式的一種, 又叫建造者模式.

生成器模式涉及4個關鍵角色:產品(Product),抽象生成器(builder),具體生成器(ConcreteBuilder),指揮者(Director).

實現層面上, 產品定義了需要什麼樣的物件, 具體生成器完成了物件的具體表示. 如果只需要一個具體的構建者,那麼抽象生成器角色和指揮者可以省略(如StringBuilder).

意圖

將一個複雜物件的構建與它的表示分離, 使得同樣的構建過程可以建立不同的表示.

類圖

設計模式十: 生成器模式(Builder Pattern)

實現

一. 定義產品

/**
 *  Car 有很多成員變數, 當然成員可能是一些複雜型別, 這裡簡化只定義一些基本型別
 */
@Data
public class Car {
    private String engine; //發動機
    private String chassis; // 底盤
    private String body; //車身
    private String wheels;  //輪子
    private String equipment; //構件, 可選
    private String radar;// 雷達, 可選
}

二. 定義抽象生成器角色

/**
 * 抽象生成器角色,定義每個元件的建立返回型別為本型別, 這樣就可以使用鏈式程式設計方式了
 * 定義了返回最終產品的介面
 */
public abstract class AbstractCarBuilder {

    //產品
    private Car car = new Car();

    protected Car getCar(){
        return car;
    }

    public abstract AbstractCarBuilder setEngine();
    public abstract AbstractCarBuilder setChassis();
    public abstract AbstractCarBuilder setBody();
    public abstract AbstractCarBuilder setWheels();
    public abstract AbstractCarBuilder setEquipment();
    public abstract AbstractCarBuilder setRadar();

    // 返回產品
    public Car build(){
        return car;
    }
}

三. 定義具體的生成器實現,這裡定義兩個

// 第一個實現
public class BMWCarBuilder extends AbstractCarBuilder {
    
    public AbstractCarBuilder setEngine() {
        Car car = this.getCar();
        car.setEngine("BMW setEngine");
        return this;
    }

    public AbstractCarBuilder setChassis() {
        Car car = this.getCar();
        car.setChassis("BMW setChassis");
        return this;
    }

    public AbstractCarBuilder setBody() {
        Car car = this.getCar();
        car.setBody("BMW setBody");
        return this;
    }

    public AbstractCarBuilder setWheels() {
        Car car = this.getCar();
        car.setWheels("BMW setWheels");
        return this;
    }

    public AbstractCarBuilder setEquipment() {
        Car car = this.getCar();
        car.setEquipment("BMW setEquipment");
        return this;
    }

    public AbstractCarBuilder setRadar() {
        Car car = this.getCar();
        car.setRadar("BMW setRadar");
        return this;
    }
}
//第二個實現
public class QQCarBuilder extends AbstractCarBuilder {
    public AbstractCarBuilder setEngine() {
        Car car = this.getCar();
        car.setEngine("QQ setEngine");
        return this;
    }

    public AbstractCarBuilder setChassis() {
        Car car = this.getCar();
        car.setChassis("QQ setChassis");
        return this;
    }

    public AbstractCarBuilder setBody() {
        Car car = this.getCar();
        car.setBody("QQ setBody");
        return this;
    }

    public AbstractCarBuilder setWheels() {
        Car car = this.getCar();
        car.setWheels("QQ setWheels");
        return this;
    }

    //沒有此元件, 不做任何事情
    public AbstractCarBuilder setEquipment() {
        return this;
    }

    //沒有此元件, 不做任何事情
    public AbstractCarBuilder setRadar() {
        return this;
    }
}

四. 定義指揮者

/**
* 指揮者角色, 用來定義構建複雜物件的演算法
* 這裡同時也定義了測試的main方法
*/
public class Director {

    private AbstractCarBuilder builder;

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

    public Car BuildCar(){
        // 鏈式構建,並返回最終的結果
        return builder
                .setWheels()
                .setRadar()
                .setEngine()
                .setChassis()
                .setBody()
                .setEquipment()
                .build();
    }

    public static void main(String[] args) {
        Director director = new Director(new QQCarBuilder());
        Car car = director.BuildCar();
        System.out.println(car.toString());

        director = new Director(new BMWCarBuilder());
        car = director.BuildCar();
        System.out.println(car.toString());
    }

}

總結

如果一個物件需要的成員變數較多, 也就是初始化所需引數過多, 過程比較複雜的話, 那麼它就適合使用Builder模式.

優點: 物件分解為元件;將物件構造封裝;構造過程可控;
缺點: 增加了類的數量.

與抽象工廠模式的區別: 二者都可以建立複雜物件, 不同的是抽象工廠強調建立一系列的產品物件, 而生成器模式著重於一步步建立一個複雜物件. Builder模式的物件是最後返回的, 抽象工廠的產品是立即返回.

相關文章