Builder Pattern(建造者模式)

定义

The intent of the Builder design pattern is to separate the construction of a complex object from its representation. By doing so the same construction process can create different representations.
将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示

应用场景

当一个对象的参数:

  • 参数很多

  • 有些参数可选,有些参数必须

  • 有些参数可以修改,有些参数设置后不可更改

时可以考虑使用建造者模式

问题

对于一个Car类,它代表一个汽车,具有多个属性,包括一些必须设置的(如品牌、型号),一些可以修改的(如颜色、内饰颜色),一些设置后不可更改的(如车架号),一些可以后期加装的(如小米Su7加装一个手机支架🐶 )

需要主动设置,没有默认值的参数:品牌、型号

可修改参数:如颜色、内饰颜色

可后期设置的参数:是否有手机支架

如果使用常见的实现方式:

  1. 折叠构造函数模式(telescoping constructor pattern )
public class Car {  
    private final String brand; // 必须  `在这里插入代码片`
    private final String model; // 必须  
    private String color; // 可选,可修改  
    private String interiorColor; // 可选,可修改  
    private final String vin; // 不可更改  
    private boolean hasPhoneHolder; // 后期加装,可修改  
  
    // 全参数构造函数  
    public Car(String brand, String model, String color, String interiorColor, String vin, boolean hasPhoneHolder) {  
        this.brand = brand;  
        this.model = model;  
        this.color = color;  
        this.interiorColor = interiorColor;  
        this.vin = vin;  
        this.hasPhoneHolder = hasPhoneHolder;  
    }  
  
    // 省略部分参数的构造函数(折叠构造函数)  
    public Car(String brand, String model, String vin) {  
        this(brand, model, null, null, vin, false);  
    }  
  
    // Getter和Setter方法(省略)  
    // ...  
}
  1. javabean模式
public class Car {  
        ...
  
    // 构造函数(通常仅用于实例化对象,不设置属性值)  
    public Car() {  
    }  
  
    // Getter和Setter方法  
    public String getInteriorColor() {
        return interiorColor;
    }

    public void setInteriorColor(String interiorColor) {
        this.interiorColor = interiorColor;
    }
  
    // 省略其他方法 ...  
}

使用折叠构造函数模式 时,当要调用一个类的构造函数时,首先要决定使用哪一个。然后构造函数里是一堆参数,需要搞清楚每个参数的类型和含义,很容易传混。

使用javabean模式 时,对于参数不可改变的方式实现起来很麻烦。

使用建造者模式可以很好的解决参数很复杂的情况

实现方式

简洁版本:

  1. 在Car中创建一个静态内部类 Builder,然后将Car中的参数都复制到Builder类中。
  2. 在Car中创建一个private的构造函数,参数为Builder类型
  3. 为Car中可以修改的参数创建setter方法
  4. 在Builder中创建一个public的构造函数,参数为Car中必须含有,且需要主动设置,没有默认值的参数。
  5. 在Builder中创建setter函数,对Car中那些可选参数进行赋值,返回值为Builder类型的实例
  6. 在Builder中创建一个build()方法,在其中做一些设置好参数后的处理,后构建Car的实例并返回
public class Car {
    private final String brand; // 必须  
    private final String model; // 必须
    private String color; // 可选,可修改
    private String interiorColor; // 可选,可修改  
    private final String vin; // 不可更改,不可主动设置
    private boolean hasPhoneHolder; // 后期加装,可修改  

//    私有构造函数
    private Car(Builder builder) {
        this.brand = builder.brand;
        this.model = builder.model;
        this.color = builder.color;
        this.interiorColor = builder.interiorColor;
        this.vin = builder.vin;
        this.hasPhoneHolder = builder.hasPhoneHolder;
    }

//    可修改参数
    public void setColor(String color) {
        this.color = color;
    }

    public void setInteriorColor(String interiorColor) {
        this.interiorColor = interiorColor;
    }

    public void setHasPhoneHolder(boolean hasPhoneHolder) {
        this.hasPhoneHolder = hasPhoneHolder;
    }
//    省略getter方法


    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + '\'' +
                ", model='" + model + '\'' +
                ", color='" + color + '\'' +
                ", interiorColor='" + interiorColor + '\'' +
                ", vin='" + vin + '\'' +
                ", hasPhoneHolder=" + hasPhoneHolder +
                '}';
    }

    public static class Builder {
        private String brand;
        private String model;
        private String color;
        private String interiorColor;
        private String vin;
        private boolean hasPhoneHolder;

        //        必须含有,且需要主动设置,没有默认值的参数
        public Builder(String brand, String model) {
            this.brand = brand;
            this.model = model;
        }

        //        可选参数
        public Builder setColor(String color) {
            this.color = color;
            return this;
        }

        public Builder setInteriorColor(String interiorColor) {
            this.interiorColor = interiorColor;
            return this;
        }

        public Builder setHasPhoneHolder(boolean hasPhoneHolder) {
            this.hasPhoneHolder = hasPhoneHolder;
            return this;
        }

//        可以在这里做一些设置好参数后的处理
        public Car build() {
//            设置颜色和内饰颜色的默认值
            if (color == null) color = "海湾蓝";
            if (interiorColor == null) interiorColor = "曜石黑";
//            生产车架,这里就直接随机生成
            vin = String.valueOf(new Random().nextInt(9000) + 1000);
//            其他处理,比如设置车架不能相同啥的
//            ...
            return new Car(this);
        }
    }
}

使用方式

在客户端使用链式调用,一步一步的把对象构建出来。

public class Main {

    public static void main(String[] args) {
        Car mySu7 = new Car.Builder("小米","Su7")
                .setColor("熔岩橙")
                .setInteriorColor("银河灰")
                .build();

        System.out.println(mySu7);
        /*Car{brand='小米', model='Su7', color='熔岩橙', interiorColor='银河灰', vin='4061', hasPhoneHolder=false}*/

//        感觉霞光紫好看, 突然想要修改颜色
        mySu7.setColor("霞光紫");
        System.out.println(mySu7);
        /*Car{brand='小米', model='Su7', color='霞光紫', interiorColor='银河灰', vin='4061', hasPhoneHolder=false}*/

//        好像加个手机支架挺方便的
        mySu7.setHasPhoneHolder(true);
        System.out.println(mySu7);
        /*Car{brand='小米', model='Su7', color='霞光紫', interiorColor='银河灰', vin='4061', hasPhoneHolder=true}*/
    }
}

可以看到使用建造者模式可以很优雅的创建这种复杂参数的对象。

参考文章

秒懂设计模式之建造者模式(Builder pattern) - 知乎 (zhihu.com)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值