构造方法有个问题,就是不太好扩展到大量的可选参数。ITEM1中提到的静态工厂方法也有这个问题。
这个item讲的就是如何选择构造器。
1. Telescoping constructor(重叠构造器)
就是常见的Android的ViewGroup
源码中的那种,一环套一环的,要自定义一个自定义控件就要复写三个构造函数。比如LinearLayout:
public LinearLayout(Context context) {
this(context, null);
}
public LinearLayout(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public LinearLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
这种优点是你可以只赋一个参数的值,缺点是有很多参数的话比如七八个,还是得挨个写,容易乱。于是有第二种方法。
2. JavaBeans
只提供一个无参构造函数。剩下的参数全用setter和getter来添加和获取。
NutritionFacts cocaCola = new NutritionFacts();
cocaCola.setServingSize(240);
cocaCola.setServings(8);
cocaCola.setCalories(100);
cocaCola.setSodium(35);
cocaCola.setCarbohydrate(27);
缺点我不太理解。书上大致是说会导致线程不安全。如下:
3. Builder
这个模式之前写SimpleBottomNavigation的时候也用到过,但没有写一个静态的builder内部类,当时只是模仿的,觉得是很巧妙,每次设置一个属性之后又返回类的instance,可以自由追加;但并没有体会到什么好处。Android的Dialog也有类似的Builder。
书中还是用了可乐的例子:
// Builder Pattern
public class NutritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate;
public static class Builder {
// Required parameters
private final int servingSize;
private final int servings;
// Optional parameters - initialized to default values
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;
}
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;
}
}
现在这样新建一个client:
NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).
calories(100).sodium(35).carbohydrate(27).build();
这就是Builder模式。
特点是:
- 等待所有的参数验证通过才会build()对象。线程安全。
- 灵活加参数,易读。
- 写起来略冗长,适合参数多的时候用。
另外
昨天我设想的是每天花一小时左右学习《Effective Java》内容,但是感觉时间有点捉襟见肘的,很多东西理解得不够深,也没很多时间去探究,加上本身项目经验也不多,对Java的理解也不够深。但是由于还有其他事情,所以目前也只能如此,不过这样学习一遍也是有好处,比如之前都不知道LinearLayout里面那种构造方法叫telescoping constructor;所以这样了解一番以后遇到了也可以深入学习。以上。
22:15 pm
14/02/2017