多个构造器参数时几种构造方法的对比--构建器函数(Builder Pattern)
1. 安全但客户端可读性差的重叠构造器模式
/** * 重叠构造器 * 通过重载构造函数,第一个构造器只包含必要参数,第二个有一个可选参数,以此类推。 * 缺点:客户端在编写时容易混乱出错,且阅读困难 * * @author JiaJia * */public class NutritionFactsOne {// (ml) requiredprivate final int servingSize;// (per container) requiredprivate final int calories;// (g) optionalprivate final int servings;// (g) optionalprivate final int fat;public NutritionFactsOne(int servingSize, int servings) {this(servingSize, servings, 0);}public NutritionFactsOne(int servingSize, int servings, int calories) {this(servingSize, servings, calories, 0);}public NutritionFactsOne(int servingSize, int servings, int calories,int fat) {this.servingSize = servingSize;this.servings = servings;this.calories = calories;this.fat = fat;}}
调用方式:
// NutritionFactsOneNutritionFactsOne a = new NutritionFactsOne(2,4,0,1);
2. 客户端可读性好但不安全的JavaBean模式
/** * JavaBean模式 * 无参构造器 + 属性setter方法。 弥补了重叠构造器模式客户端代码难以编写且阅读困难的不足 * 缺点:构造动作被拆分到几次调用中,阻止了把类做成不可变类的可能 需要额外的努力来保证线程安全 * * @author JiaJia * */public class NutritionFactsTwo {// (ml) requiredprivate int servingSize = -1;// (per container) requiredprivate int servings = -1;// (g) optionalprivate int calories = 0;// (g) optionalprivate int fat = 0;public NutritionFactsTwo() {}public void setServingSize(int servingSize) {this.servingSize = servingSize;}public void setServings(int servings) {this.servings = servings;}public void setCalories(int calories) {this.calories = calories;}public void setFat(int fat) {this.fat = fat;}}
调用方式:
// NutritionFactsTwoNutritionFactsTwo b = new NutritionFactsTwo();b.setServingSize(2);b.setServings(4);b.setCalories(0);b.setFat(1);
3. 客户端可读性好且安全的Builder模式
/** * 构建器模式 * 客户端通过静态成员类-builder来创建对象 * 1.通过Builder自身的构造函数,其中包含目标对象所有的必要参数,得到Builder对象 * 2.调用Builder中的类似于setter的方法(返回类型是Builder),设置可选参数 * 3.调用无参的build方法来生成不可变对象 * 优点:弥补了前两者的不足,既能保证像重叠构造器模式那样的安全性, 又能保证像JavaBean模式那么好的可读性。 * * @author JiaJia * */public class NutritionFactsThree {private final int servingSize;private final int servings;private final int calories;private final int fat;public static class Builder {// (ml) requiredprivate final int servingSize;// (per container) requiredprivate final int servings;// (g) optionalprivate int calories;// (g) optionalprivate int fat;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) {fat = val;return this;}public NutritionFactsThree build() {return new NutritionFactsThree(this);}}private NutritionFactsThree(Builder builder) {this.servingSize = builder.servingSize;this.servings = builder.servings;this.calories = builder.calories;this.fat = builder.fat;}}
调用方式:
// NutritionFactsThreeNutritionFactsThree c = new NutritionFactsThree.Builder(2,4).calories(0).fat(1).build();