当创建一个有多个参数对象时通常使用三种方式来创建
1.使用构造器创建
使用构造器时可能会针对不同参数创建多个构造器,发生构造器重载,使用起来不太方便,还要查看使用哪个构造器,并且多个参数也容易导致传参错误(参数顺序传错),生成错误的对象。对于必选参数和可选参数构造器的创建也要注意
2.使用JavaBean
JavaBean 模式就是使用 set(),方法对对象进行属性赋值,这种方式需要多次set,比较灵活,如果是必选参数就要通过一个构造器设置,并且不能使用空构造器。但是这种方式可以随时使用set()方法对对象的属性值进行修改,不能生成一个不可变对象。
3.使用builder模式(创建者设计模式)
该设计模式在对象内部使用一个Builder内部类,通过对builder对象的赋值来对外层对象属性赋值,外层对象的构造器私有化,避免外部创建,并且没有set()方法,生成的属性值不可改变。还可以在builder设置属性值时对参数校验。
下面是代码,摘抄自 effective-java
/**
* builder 模式创建对象
* 产生的对象不可变
*/
public class NutritionFacts {
// final 不允许更改
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
// 仅在构造器时初始化属性, 构造器私有, 只能内部创建对象
private NutritionFacts(Builder builder){
this.servingSize = builder.servingSize;
this.servings = builder.servings;
this.calories = builder.calories;
this.fat = builder.fat;
this.sodium = builder.sodium;
}
@Override
public String toString() {
return "NutritionFacts{" +
"servingSize=" + servingSize +
", servings=" + servings +
", calories=" + calories +
", fat=" + fat +
", sodium=" + sodium +
'}';
}
// 使用 build 内部类创建对象
public static class Builder{
// 必须有的属性
private final int servingSize;
private final int servings;
// 选填的属性
private int calories = 0;
private int fat = 0;
private int sodium = 0;
// 必填属性在构造器中
public Builder(int servingSize, int servings){
this.servingSize = servingSize;
this.servings = servings;
}
// 选填属性通过方法创建
public Builder calories(int val){
calories = val;
return this;
}
public Builder fat(int val){
// 参数检查
if (val > 100) throw new IllegalArgumentException();
fat = val;
return this;
}
public Builder sodium(int val){
sodium = val;
return this;
}
// 创建对象
public NutritionFacts build (){
return new NutritionFacts(this);
}
}
public static void main(String[] args) {
NutritionFacts nf1 = new Builder(3, 5).build();
System.out.println(nf1);
NutritionFacts nf2 = new Builder(3, 5).calories(12).fat(99).build();
System.out.println(nf2);
}
}