Android 编码规范:(二)遇到多个构造器参数时要考虑用构建器
静态工厂和构造器有个共同的局限性:它们都不能很好地扩展到大量的可选参数。考虑用一个类表示包装食品外面显示的营养成分标签。这些标签中有几个域是必须的:每份的含量、每罐的含量以及每份的卡路里,还有超过20个可选域:总脂肪量、饱和脂肪量、转化脂肪、胆固醇、钠等等。大多数产品在某几个可选域中都会有非零的值。
对于这样的类,应该用哪种构造器或者静态方法来编写呢?
1. 重叠构造器模式
- // Telescoping constructor pattern - does not scale well!
- public class NutritionFacts {
- private final int servingSize; // (mL) required
- private final int servings; // (per container) required
- private final int calories; // optional
- private final int fat; // (g) optional
- private final int sodium; // (mg) optional
- private final int carbohydrate; // (g) optional
- public NutritionFacts(int servingSize, int servings) {
- this(servingSize, servings, 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;
- }
- public static void main(String[] args) {
- NutritionFacts cocaCola =
- new NutritionFacts(240, 8, 100, 0, 35, 27);
- }
- }
2. JavaBeans模式
3. 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;
- }
- public static void main(String[] args) {
- NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).
- calories(100).sodium(35).carbohydrate(27).build();
- }
- }
简而言之,如果类的构造器或者静态工厂中具有多个参数,设计这种类时,Builder模式就是种不错的选择,特别是当大多数参数都是可选的时候。与使用传统的重叠构造器模式相比,使用Builder模式的客户端代码将更易于阅读和编写,构造器也比JavaBeans更加安全。