<div
class="iteye-blog-content-contain" style="font-size: 16px">
今天是讲《Effective Java》中的第二条:遇到多个
构造器参数时要考虑用构建器
这节我们先看代码(这些代码是我直接从书上抄下来的,这节的代码示例给的非常好)
示例一:
public class NutritionFacts{
private final int servingSize; //required
private final int servings; //required
private final int calories; //optional
private final int fat;
private final int sodium;
private final int carbohydrate;
public NutritionFacts(int servingSize , int servings){
this(servingSize,servings,calories,0);
}
Public NutritionFacts(int servingSize, int servings, int calories){
This(servingSize,servings,calories ,0);
}
Public NutritionFacts(int servingSize, int servings, int calories, int fat){
This(servingSize,servings,calories,fat,0);
}
Public NutritionFacts(int servingSize,int servings,int calories,int fat,int sodium){
This(servingSize,servings,calories,fat,sodium,0);
}
Public NutritionFacts(int servingSize,int servings,int calories,int fat,int sodium,int carbohydrate){
this. servingSize= servingSize;
this. Servings= servings;
this. calories= calories;
this.fat=fat;
this. sodium= sodium;
this. carbohydrate= carbohydrate;
}
}
那我们都是这么使用的:
NutritionFacts cocaCola= new NutritionFacts(240,8,100,0,0,27);
有些参数我们本来是不想设置的,但是又不得不给它们传值,于是给传个0。现在是6个参数,如果是10个或再多呢?对于客户端代码是很难写的,那如果有两参数你给记错了,传错值,那编译器也不会提示
错误,到程序运行时出现了错误,那就更麻烦了。
使用JavaBean模式来替代:
public class NutritionFacts{
private int servingSize=-1; //required
private int servings=-1; //required
private int calories=0; //optional
private int fat=0;
private int sodium=0;
private int carbohydrate=0;
public NutritionFacts(){}
public void setServingSize(int val){servingSize = val;}
public void setServings (int val){ servings = val;}
public void setCalories (int val){ calories = val;}
public void setFat(int val){fat = val;}
public void setSodium (int val){ sodium = val;}
public void setCarbohydrate (int val){ carbohydrate = val;}
}
调用时:
NutritionFacts cocaCola= new NutritionFacts();
cocaCola. setServingSize(240);
cocaCola. setServings(8);
cocaCola. setCalories(100);
cocaCola. setCarbohydrate(27);
JavaBean模式的缺点:构造过程中被分割到几个调用中,在构造过程中Javabean可能处于不一致状态。另外一点,JavaBean模式阻止了把类做成不可变的可能。
幸运有有下面这种:
public class NutritionFacts{
private final int servingSize; //required
private final int servings; //required
private final int calories; //optional
private final int fat;
private final int sodium;
private final int carbohydrate;
public static class Builder{
private final int servingSize;
private final int servings;
private int calories=0; //optional
private int fat=0;
private int sodium=0;
private int carbohydrate=0;
public Builder(int servingSize,int servings){
this.servingSize = servingSize;
this.serving=servings;
}
public Butilder calories(int val){
calories=val; return this;
}
public Butilder fat (int val){
fat =val; return this;
}
public Butilder sodium (int val){
sodium =val; return this;
}
public Butilder carbohydrate (int val){
carbohydrate =val; return this;
}
public NutritionFacts build(){
return new NutritionFacts(this);
}
}
private NutritionFacts(Builder builder){
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
fat = builder.fat;
sodium = builder.sodium;
carbohydrate = builder.carbohydrate;
}
}
NutritionFacts cocaCola=new NutritionFacts.Builder(240,8).calories(100).carbohydrate(27).build();
build方法可以检验这些约束条件,将参数从bulider拷贝到对象中之后,并在对象域而不是buider域中对它们进行检验。
总结一下什么时候使用Builder模式呢?
如果类的构造器或者静态工厂方法中具有多个参数,设计这种类时,Builder模式就是中不错的选择,特别是在大多数参数是可选的情况下。
</div>