第二章的第二条经验
遇到多个构造器参数时要考虑用构建器
使用场景举例
实现一个食品营养成分的类,有超过20个可选域:如总脂肪量、饱和脂肪量等等;
普通的实现方法
重叠构造器模式和JavaBean模式。
重叠构造器的缺点:当参数很多时,客户端很难编码。
JavaBean模式的缺点:在构造时,线程不安全,容易使对象状态不一致。
建议的方式
构建器模式,既可以保证安全性,又可以像JavaBean那样保证可读性。
public class NutritionFacts {
//私有不可改变
private final int servingSize;
private final int servings;
private final int claories;
private final int sodium;
private final int carbohydrate;
//公有 静态Builder内部类
public static class Builder {
private final int servingSize;
private final int servings;
private int calories = 0;
private int fat = 0;
private int carbohydrate = 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){
fat = val;
return this;
}
public Builder carbohydrate(int val){
carbohydrate = val;
return this;
}
public Builder sodium(int val){
sodium = val;
return this;
}
//通过builder方法,构造NutritionFacts 类对象
public NutritionFacts build(){
return new NutritionFacts(this);
}
}
//私有化被构造对象的构造方法
private NutritionFacts(Builder builder){
servingSize = builder.servingSize;
serving = builder.servings;
calories = builder.calories;
fat = builder.fat;
sodium = builder.sodium;
carbohydrate = builder.carbohydrate;
}
}
//客户端代码
NutritionFacts cocaCola = new NutritionFacts.Builder(240,8).
calories(100).
fat(20).
sodium(35).
build();
优势
构建器模式,可以像构造器一样对其参数强加约束条件;
构建器可以在设置参数的方法上设置个可变参数;
构建器非常灵活,可以在构建对象期间对参数进行调整,也可以随着对象的不同而改变,也可以自动填充某些域,如每次都自动增加序列号;
可以生成一个构建器的抽象工厂,将这个抽象工厂作为方法的参数,使该方法可以创建一个或者多个对象。
//一个T类型对象的构建器
public interface Builder<T> {
public T build();
}
不足
为了创建对象,必须先创建它的构建器,在强调性能的场景下可能是个问题,并且编码还比较冗长,因此只有在很多参数场景下才使用。
建议
如果类的构造器或者静态工厂中具有多个参数,设计这种类时,Builder模式就是种不错的选择