Effective Java-2. 当构造方法参数过多时使用builder模式
背景
静态工厂和构造方法不能很好的拓展到很多可选参数的场景,因为参数过多的时候,调用其构造方法不太能知道每个位置参数的含义,容易出bug
那么为这个类编写什么样下的构造方法或静态工厂呢?
- 可伸缩构造方法模式
- 例子:
- 这个构造方法的调用需要许多你不想设置的参数,但是你不得不为它们传递一个值。 在这种情况下,我们为属性传递了 0 值。随着参数的增加容易失控
- 难以读懂
// Telescoping constructor pattern - does not scale well!
class NutritionFacts {
private final int servingSize; // (mL) required
private final int servings; // (per container) required
private final int calories; // (per serving) optional
private final int fat; // (g/serving) optional
private final int sodium; // (mg/serving) optional
private final int carbohydrate; // (g/serving) 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;
}
}
- JavaBeans模式
- 使用无参构造方法创建对象,调用setter方法设置成员属性
- 构造对象过程被setter方法多次分割,可能处于不一致状态
- 排除了让类不可变的的可能性
// 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; // Required; no default value
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; }
}
// ==================调用形式===================
NutritionFacts cocaCola = new NutritionFacts();
cocaCola.setServingSize(240);
cocaCola.setServings(8);
cocaCola.setCalories(100);
cocaCola.setSodium(35);
cocaCola.setCarbohydrate(27);
Builder模式
- 可以生成流畅的API,易于阅读
- builder 可以有多个可变参数,因为每个参数都是在它自己的方法中指定的,可以将传递给多个调用的参数聚合到单个属性中
- 单个 builder 可以重复使用来构建多个对象,builder 的参数可以在构建方法的调用之间
进行调整,以改变创建的对象,可以在创建时自动添加一些属性(例如递增的序列号)
具体用法参考建造者模式!!!
缺点:
- 为了创建对象,必须创建一个Builder对象,可能会影响性能
- builder模式比神所构造方法模式冗长,因此builder模式适用有足够的参数(或者未来可能有)
本文来自博客园,作者:WYia,转载请注明原文链接:https://www.cnblogs.com/wyia/p/16978667.html