在Java中遇到多个参数时,有3种方式可以构造类。
一、重叠构造器(telescoping constructor)模式
这种模式下,在类中有多个使用不同参数的构造函数,需要什么参数,就写一个相应的构造函数。结果是随着参数数目的增加,代码臃肿不堪。
二、JavaBean模式
这种模式下,通过调用一个无参构造函数来创建对象,然后通过setter方法来设置必要的参数。这种代码创建实例很容易,读起来也不费力,但是它将构造过程分到了很多setter调用中,设置参数的时候,JavaBean可能处于不一致的状态。类无法仅仅通过检验构造器参数的有效性保证一致性。
三、Builder模式
Builder模式像个构造器一样,它的setter方法返回builder本身,以便可以把调用链接起来。安卓里面AlertDialog就是通过Builder模式来初始化的。下面是Effective Java书中的一个例子,在此作了部分修改和简化,其中Builder类通过书中提到的泛型来实现。
public class NutritionFacts {
private final int size;
private final int fat;
private final int sodium;
private final int calories;
private NutritionFacts(Builder builder) {
this.size = builder.size;
this.fat = builder.fat;
this.sodium = builder.sodium;
this.calories = builder.calories;
}
public int getSize() {
return size;
}
public int getFat() {
return fat;
}
public int getSodium() {
return sodium;
}
public int getCalories() {
return calories;
}
public static class Builder implements BuilderInterface<NutritionFacts> {
// Required parameters
private final int size;
private final int fat;
// Optional parameters - initialized to default values
private int sodium = 0;
private int calories = 0;
public Builder setSodium(int sodium) {
this.sodium = sodium;
return this;
}
public Builder setCalories(int calories) {
this.calories = calories;
return this;
}
public Builder(int size, int fat) {
this.size = size;
this.fat = fat;
}
@Override
public NutritionFacts build() {
return new NutritionFacts(this);
}
}
}
BuilderInterface接口如下所示:
public interface BuilderInterface<T> {
T build();
}
这样,新建一个NutritionFacts对象,只需要使用下面的代码:
NutritionFacts cocaCola = new NutritionFacts.Builder(1,2).setSodium(3).setCalories(4).build();
在此需要注意的地方有:
1. 初始化必须使用的变量使用final修饰,是为了防止变量发生变化,只允许初始化设值。
2. NutritionFacts的构造函数使用private修饰,即只允许通过Builder来实例化对象。
总结
简而言之,如果类的构造器或者静态工厂中具有多个参数,设计这种类时,Builder模式就是种不错的选择,特别是当大多数参数都是可选的时候。与使用传统的重叠构造器模式相比,使用Builder模式的客户端代码将更易于阅读和编写,构建器也比JavaBean更加安全。