文章目录
- 1、建造者模式
 - 2、案例:共享单车的创建
 - 3、其他用途
 
1、建造者模式
- 某个对象的构建复杂
 - 将复杂的对象的创建 和 属性赋值所分离,使得同样的构建过程可以创建不同的表示
 - 建造的过程和细节调用者不需要知道,只需要通过构建者去进行操作
 
如,主机这个负责对象的构建,分离承诺内存条、主板这些部件,再组装构建。内存条替换一个别的,出来就是一个不同的对象。

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

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

 具体的代码如下:
//自行车类
@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);
    }
}
                

















