EffectiveJava-2.遇到多个构造器参数时要考虑用构建器
2017-02-20 14:56
513 查看
静态工厂和构造器有个共同的局限性:它们都不能很好地扩展到大量的可选参数。考虑用一个类表示包装食品外面显示的营养成份标签。这些标签中有几个域是必需的:每份的含量、每罐的含量以及每份的卡路里,还有超过20个可选域:总脂肪量、饱和脂肪量、转化脂肪、胆固醇、钠等等。大多数产品都只有几个可选域中会有非零的值。
对于这样的类,应该用哪种构造器或者静态方法来编写呢?程序员一向习惯采用telescoping constructor模式,在这种模式下,你提供一个只有必要参数的构造器,第二个构造器有一个可选参数,第三个有两个可选参数,依此类推,最后一个构造器包含所有可选参数。下面有个示例,为了简单起见,它只显示四个可选域:
当你想要创建实例的时候,就利用参数列表最短的构造器,但该列表中包含了要设置的所有参数:
这种模式不具备telescoping constructor模式的任何缺点。说得明白一点,就是创建实例很容易,这样产生的代码读起来也很容易:
注意NutritionFacts是不可变的,所有的默认参数值都单独放在一个地方。builder的setter方法返回builder本身,以便可以把调用链接起来。下面就是客户端代码:
注意,可以声明NutritionFacts.Builder类来实现Builder
对于这样的类,应该用哪种构造器或者静态方法来编写呢?程序员一向习惯采用telescoping constructor模式,在这种模式下,你提供一个只有必要参数的构造器,第二个构造器有一个可选参数,第三个有两个可选参数,依此类推,最后一个构造器包含所有可选参数。下面有个示例,为了简单起见,它只显示四个可选域:
// 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 s 4000 ervings, 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; } }
当你想要创建实例的时候,就利用参数列表最短的构造器,但该列表中包含了要设置的所有参数:
// JavaBeans Pattern - allows inconsistency, mandates mutability public class NutritionFacts { // Parameters initialized to default values (if any) private int servingSize = -1; // Required; no default value private int servings = -1; // " " " " private int calories = 0; private int fat = 0; private int sodium = 0; private int carbohydrate = 0; public NutritionFacts() { } // Setters 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; } }
这种模式不具备telescoping constructor模式的任何缺点。说得明白一点,就是创建实例很容易,这样产生的代码读起来也很容易:
// 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; private NutritionFacts(Builder builder) { servingSize = builder.servingSize; servings = builder.servings; calories = builder.calories; fat = builder.fat; sodium = builder.sodium; carbohydrate = builder.carbohydrate; } public static class Builder { // Required parameters private dee6 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); } } }
注意NutritionFacts是不可变的,所有的默认参数值都单独放在一个地方。builder的setter方法返回builder本身,以便可以把调用链接起来。下面就是客户端代码:
// A builder for objects of type T public interface Builder { public T build(); }
注意,可以声明NutritionFacts.Builder类来实现Builder
相关文章推荐
- EffectiveJava 第2条 :遇到多个构造器参数时要考虑用构建器(2)
- EffectiveJava 第2条 :遇到多个构造器参数时要考虑用构建器(1)
- effective java(一)遇到多个构造器参数 时要考虑用构建器
- Effective-Java学习笔记 遇到多个构造器参数时要考虑用构建器
- 第二条:遇到多个构造器参数时要考虑用构建器
- 第2条:遇到多个构造器参数时要考虑用构建器
- Effective Java (2) - 遇到多个构造器参数时要考虑用构建器
- Effective Java第二条:遇到多个构造器参数时要考虑用构建器
- 创建和销毁对象(2)——遇到多个构造器参数是要考虑用构建器
- 遇到多个构造器参数时要考虑用构建器
- 遇到多个构造器参数时要考虑用构建器
- Android 编码规范:(二)遇到多个构造器参数时要考虑用构建器
- Android 编码规范:(二)遇到多个构造器参数时要考虑用构建器
- 第二条:遇到多个构造器参数时要考虑用构建器
- 遇到多个构造器参数考虑用构建器(Builder)
- 第2条 创建和销毁对象——遇到多个构造器参数时要考虑用构建器
- Android 编码规范:(二)遇到多个构造器参数时要考虑用构建器
- 遇到多个构造器参数时要考虑用构建器——Effective Java 读书笔记
- EJ.02 遇到多个构造器参数时要考虑用构建器
- Effective Jave——第2条: 遇到多个构造器参数时考虑使用构建器(Builder)