设计模式 - 建造者模式

64 阅读4分钟

image.png

有两种建造者模式

  1. 有导演类(场景:消费者从不同的方案中选择一个方案获取目标产物)
  2. 无导演类(场景:消费者DIY获取目标产物)

有导演类

代码文件如下

image.png

  1. 目标产物的定义
public class Car {
    private String tire;
    private String window;
    private String light;
    private String trumpet;

    public String getTire() {
        return tire;
    }

    public void setTire(String tire) {
        this.tire = tire;
    }

    public String getWindow() {
        return window;
    }

    public void setWindow(String window) {
        this.window = window;
    }

    public String getLight() {
        return light;
    }

    public void setLight(String light) {
        this.light = light;
    }

    public String getTrumpet() {
        return trumpet;
    }

    public void setTrumpet(String trumpet) {
        this.trumpet = trumpet;
    }

    @Override
    public String toString() {
        return "Car{" +
                "tire='" + tire + ''' +
                ", window='" + window + ''' +
                ", light='" + light + ''' +
                ", trumpet='" + trumpet + ''' +
                '}';
    }
}

2.定义方案的内容

/**
 * 抽象的建造者:方法
 */
public abstract class Builder {
    public abstract void buildTire(); // 装轮胎
    public abstract void buildWindow(); // 装窗户
    public abstract void buildLight(); // 装大灯
    public abstract void buildTrumpet(); // 装喇叭

    // 完工:得到车子
    public abstract Car getCar();
}

3.使用统一的方案,给到不同的厂家,设置不同的目标产物的内容

/**
 * 具体的建造者:工人
 */
public class FerrariWorker extends Builder {
    private Car car;

    public FerrariWorker() {
        this.car = new Car();
    }

    @Override
    public void buildTire() {
        this.car.setTire("法拉利装轮胎");
        System.err.println("法拉利装轮胎");
    }

    @Override
    public void buildWindow() {
        this.car.setWindow("法拉利装窗户");
        System.err.println("法拉利装窗户");
    }

    @Override
    public void buildLight() {
        this.car.setLight("法拉利装大灯");
        System.err.println("法拉利装大灯");
    }

    @Override
    public void buildTrumpet() {
        this.car.setTrumpet("法拉利装喇叭");
        System.err.println("法拉利装喇叭");
    }

    @Override
    public Car getCar() {
        return this.car;
    }
}
/**
 * 具体的建造者:工人
 */
public class PorscheWorker extends Builder {
    private Car car;

    public PorscheWorker() {
        car = new Car();
    }

    @Override
    public void buildTire() {
        car.setTire("保时捷装轮胎");
        System.err.println("保时捷装轮胎");
    }

    @Override
    public void buildWindow() {
        car.setWindow("保时捷装窗户");
        System.err.println("保时捷装窗户");
    }

    @Override
    public void buildLight() {
        car.setLight("保时捷装大灯");
        System.err.println("保时捷装大灯");
    }

    @Override
    public void buildTrumpet() {
        car.setTrumpet("保时捷装喇叭");
        System.err.println("保时捷装喇叭");
    }

    @Override
    public Car getCar() {
        return this.car;
    }
}

4.指挥者(导演类)给定不同的建造顺序

/**
 * 指挥:核心。负责指挥构建一个工程,按什么顺序构建工程由它决定
 */
public class Director {
    /**
     * 顺序装车
     */
    public Car ascBuildCar(Builder builder) {
        builder.buildTire();
        builder.buildWindow();
        builder.buildLight();
        builder.buildTrumpet();

        return builder.getCar();
    }

    /**
     * 倒序装车
     */
    public Car descBuildCar(Builder builder) {
        builder.buildTrumpet();
        builder.buildLight();
        builder.buildWindow();
        builder.buildTire();

        return builder.getCar();
    }
}

5.指挥者(导演类 Director)指挥不同的建造者(Worker)按指挥顺序进行建造

public class test {
    /**
     * 常规用法,指挥者(导演类 Director)指挥不同的建造者(Worker)按指挥顺序进行建造
     */
    public static void main(String[] args) {
        Director director = new Director();
        Car ascPorsche = director.ascBuildCar(new PorscheWorker());
        System.err.println(ascPorsche.toString());

        Car descPorsche = director.descBuildCar(new PorscheWorker());
        System.err.println(descPorsche.toString());

        Car ascFerrari = director.ascBuildCar(new FerrariWorker());
        System.err.println(ascFerrari.toString());

        Car descFerrari = director.descBuildCar(new FerrariWorker());
        System.err.println(descFerrari.toString());
    }
}

输出结果如下

保时捷装轮胎
保时捷装窗户
保时捷装大灯
保时捷装喇叭
Car{tire='保时捷装轮胎', window='保时捷装窗户', light='保时捷装大灯', trumpet='保时捷装喇叭'}
保时捷装喇叭
保时捷装大灯
保时捷装窗户
保时捷装轮胎
Car{tire='保时捷装轮胎', window='保时捷装窗户', light='保时捷装大灯', trumpet='保时捷装喇叭'}
法拉利装轮胎
法拉利装窗户
法拉利装大灯
法拉利装喇叭
Car{tire='法拉利装轮胎', window='法拉利装窗户', light='法拉利装大灯', trumpet='法拉利装喇叭'}
法拉利装喇叭
法拉利装大灯
法拉利装窗户
法拉利装轮胎
Car{tire='法拉利装轮胎', window='法拉利装窗户', light='法拉利装大灯', trumpet='法拉利装喇叭'}

无导演类

代码文件如下

image.png

  1. 目标产物的定义,并允许给到默认值
public class Car {
    private String tire = "tireOne";
    private String window = "windowOne";
    private String light = "lightOne";
    private String trumpet = "trumpetOne";

    public String getTire() {
        return tire;
    }

    public void setTire(String tire) {
        this.tire = tire;
    }

    public String getWindow() {
        return window;
    }

    public void setWindow(String window) {
        this.window = window;
    }

    public String getLight() {
        return light;
    }

    public void setLight(String light) {
        this.light = light;
    }

    public String getTrumpet() {
        return trumpet;
    }

    public void setTrumpet(String trumpet) {
        this.trumpet = trumpet;
    }

    @Override
    public String toString() {
        return "Car{" +
                "tire='" + tire + ''' +
                ", window='" + window + ''' +
                ", light='" + light + ''' +
                ", trumpet='" + trumpet + ''' +
                '}';
    }
}

2.定义方案的内容,并允许消费者设定方案

public abstract class Builder {

    public abstract Builder buildTire(String tire); // 装轮胎
    public abstract Builder buildWindow(String window); // 装窗户
    public abstract Builder buildLight(String light); // 装大灯
    public abstract Builder buildTrumpet(String trumpet); // 装喇叭

    // 完工:得到车子
    public abstract Car getCar();
}

3.工人根据消费者的内容进行目标产物的设置

public class Worker extends Builder {
    private Car car;

    public Worker() {
        car = new Car();
    }

    @Override
    public Builder buildTire(String tire) {
        car.setTire(tire);
        return this;
    }

    @Override
    public Builder buildWindow(String window) {
        car.setWindow(window);
        return this;
    }

    @Override
    public Builder buildLight(String light) {
        car.setLight(light);
        return this;
    }

    @Override
    public Builder buildTrumpet(String trumpet) {
        car.setTrumpet(trumpet);
        return this;
    }

    @Override
    public Car getCar() {
        return this.car;
    }
}

4.最终消费者DIY建造

/**
 * 无导演类
 * 场景:麦当劳点套餐,默认有一个套餐内容,消费者可以选择更改套餐里的食物
 */
public class test {
    public static void main(String[] args) {
        Car carOne = new Worker().getCar();
        System.err.println(carOne.toString());

        // 链式编程,在原来的基础上允许自由组合,如果不组合,也有默认值
        Car carTwo = new Worker().buildTire("tireTwo").buildTrumpet("trumpetTwo").getCar();
        System.err.println(carTwo.toString());
    }
}

输出结果如下

Car{tire='tireOne', window='windowOne', light='lightOne', trumpet='trumpetOne'}
Car{tire='tireTwo', window='windowOne', light='lightOne', trumpet='trumpetTwo'}