1、建造者模式

  • 某个对象的构建复杂
  • 将复杂的对象的创建 和 属性赋值所分离,使得同样的构建过程可以创建不同的表示
  • 建造的过程和细节调用者不需要知道,只需要通过构建者去进行操作

如,主机这个负责对象的构建,分离承诺内存条、主板这些部件,再组装构建。内存条替换一个别的,出来就是一个不同的对象。

【Java设计模式】五、建造者模式-LMLPHP

建造者模式相关角色:

  • 产品类:复杂对象,主机
  • 抽象建造者类Builder:规定要实现复杂对象的哪些部件的创建
  • 具体建造者类ConcreteBuilder:实现Builder,完成各个部件的具体创建
  • 指挥者类Director:保证对象的各个部分按照某种顺序创建

【Java设计模式】五、建造者模式-LMLPHP

2、案例:共享单车的创建

摩拜单车和ofo单车。Bike是产品,包含车架,车座等组件;Builder是抽象建造者,MobikeBuilder和OfoBuilder是具体的建造者,Director是指挥者。

【Java设计模式】五、建造者模式-LMLPHP
具体的代码如下:

//自行车类
@Data
public class Bike {
    private String frame;  //车架
    private String seat;   //座椅


}

抽象构建者Builder定义哪些部分要构建:

// 抽象 builder 类
public abstract class Builder {

    protected Bike mBike = new Bike();

    public abstract void buildFrame();   //构建车架
    public abstract void buildSeat();    //构建座椅
    public abstract Bike createBike();   //构建自行车
    
}

写具体的构建者:

//摩拜单车Builder类
public class MobikeBuilder extends Builder {

    @Override
    public void buildFrame() {
        mBike.setFrame("铝合金车架");
    }

    @Override
    public void buildSeat() {
        mBike.setSeat("真皮车座");
    }

    @Override
    public Bike createBike() {
        return mBike;
    }
}

//ofo单车Builder类
public class OfoBuilder extends Builder {

    @Override
    public void buildFrame() {
        mBike.setFrame("碳纤维车架");
    }

    @Override
    public void buildSeat() {
        mBike.setSeat("橡胶车座");
    }

    @Override
    public Bike createBike() {
        return mBike;
    }
}

指挥者类:

//指挥者类
public class Director {
    private Builder mBuilder;   //声明Builder类型的变量

    public Director(Builder builder) {
        mBuilder = builder;
    }
	
	//组装自行车的方法
    public Bike construct() {
        mBuilder.buildFrame();
        mBuilder.buildSeat();
        return mBuilder.createBike();
    }
}

客户端测试:

public class Client {
    public static void main(String[] args) {
        showBike(new OfoBuilder());
        showBike(new MobikeBuilder());
    }
    private static void showBike(Builder builder) {
        Director director = new Director(builder);   //创建指挥者
        Bike bike = director.construct();   //让指挥者指挥组装
        System.out.println(bike.getFrame());
        System.out.println(bike.getSeat());
    }
}

再有新的单车公司加入,只需实现一个新的建造者类即可,符合开闭原则。但如果创建的产品组成部分差异很大,则不适合用建造者模式,比如要再造个电脑对象。

3、其他用途

@Setter
@Getter
public class Phone {
    private String cpu;
    private String screen;
    private String memory;
    private String mainboard;

    public Phone(String cpu, String screen, String memory, String mainboard) {
        this.cpu = cpu;
        this.screen = screen;
        this.memory = memory;
        this.mainboard = mainboard;
    }
}

对于属性多的对象,创建其对象往往可读性很差,如:

//构建Phone对象
Phone phone = new Phone("intel","三星屏幕","金士顿","华硕");

重构一下(@Builder注解的思路):

public class Phone {

    private String cpu;
    private String screen;
    private String memory;
    private String mainboard;
	
	//私有的构造方法
    private Phone(Builder builder) {
        cpu = builder.cpu;
        screen = builder.screen;
        memory = builder.memory;
        mainboard = builder.mainboard;
    }

    public static final class Builder {
        private String cpu;
        private String screen;
        private String memory;
        private String mainboard;

        public Builder() {}

        public Builder cpu(String val) {
            cpu = val;
            return this;
        }
        public Builder screen(String val) {
            screen = val;
            return this;
        }
        public Builder memory(String val) {
            memory = val;
            return this;
        }
        public Builder mainboard(String val) {
            mainboard = val;
            return this;
        }
        //!!!!!
        public Phone build() {
            return new Phone(this);
         }
    }
    @Override
    public String toString() {
        return "Phone{" +
                "cpu='" + cpu + '\'' +
                ", screen='" + screen + '\'' +
                ", memory='" + memory + '\'' +
                ", mainboard='" + mainboard + '\'' +
                '}';
    }
}


此时就可链式编程创建这个对象(new Phone.Builder()创建静态内部类对象):

public class Client {
    public static void main(String[] args) {
        Phone phone = new Phone.Builder()
                .cpu("intel")
                .mainboard("华硕主板")
                .memory("金士顿内存")
                .screen("三星屏幕")
                .build();
        System.out.println(phone);
    }
}
03-05 11:00