Item2:遇到多个构造参数时要考虑用构造器

构造方法有个问题,就是不太好扩展到大量的可选参数。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);

缺点我不太理解。书上大致是说会导致线程不安全。如下:

Item2:遇到多个构造参数时要考虑用构造器_第1张图片
11.png

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

你可能感兴趣的:(Item2:遇到多个构造参数时要考虑用构造器)