静态工厂和构造器有个共同的局限性:他们都不能很好的扩展大量的可选参数,
比如包装食品营养成分标签,含量,卡路里,等等,有可能会超过20个可选域,对于这样的类,应该用那种构造器或静态方法来写呢,
构造器:
程序员一般习惯采用重载构造器来实现,第一个构造器,提供一个必要参数,第二个构造器提供,一个必要参数,一个可选参数,依次类推.
public NutritionFacts(int servingSize){}
public NutritionFacts(int servingSize,int calories){}
public NutritionFacts(int servingSize,int calories,int fat){}
缺点
构造器调用通常需要许多本不想设置参数,但是不得不为他们传递值.随着参数数目的增加,就很快失去了控制
javabean模式:
这种模式下调用一个午餐构造器来创建对象,然后调用setter方法来设置每个必要的参数,以及每个可选参数.
public class NutritionFacts{
private int servingSize=-1;
private int servings=-1;
private int calories=0;
...getter setter省略
}
优点:弥补了重叠构造器模式的不足,创建实例很容易,代码易读性强
NutritionFacts cocaCola=new NutritionFacts();
cocaCola.setServingSize(22);
cocaCola.setServings(22);
...
缺点:
其构造过程中被分到几个调用中,在构造过程中JavaBean可能处于不一致的状态,这种失败与包含错误代码,类无法仅仅通过检验构造器参数的有效性来保证一致性,试图使用不一致状态的对象,将会导致失败,这种失败与包含错误的代码大相径庭,因此它调试起来非常困难,另一点不足,JavaBean阻止了把类做成不可变类的可能,这就需要额外的努力来确保他的线程安全.
构建器模式:
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 Bulider{
private int servingSize;
private int servings;
private int calories=0;
private int fat=0;
private int sodium=0;
private int carbohydrate=0;
public Bulider( int servingSize,int servings) {
this.servings=servings;
this.servingSize=servingSize;
}
public Bulider calories( int var) {
this.calories=var;
return this;
}
public Bulider fat( int var) {
this.fat=var;
return this;
}
public Bulider sodium( int var) {
this.sodium=var;
return this;
}
public Bulider carbohydrate( int var) {
this.carbohydrate=var;
return this;
}
public NutritionFacts bulid() {
return new NutritionFacts(this);
}
}
private NutritionFacts(Bulider bulider) {
servings=bulider.servings;
servingSize=bulider.servingSize;
calories=bulider.calories;
fat=bulider.calories;
sodium=bulider.sodium;
carbohydrate=bulider.carbohydrate;
}
}
//客户端测试
@Test
public void codeTest() {
NutritionFacts nutritionFacts=new NutritionFacts.Bulider(240, 8).
calories(100).sodium(33).carbohydrate(22).bulid();
}
优势:
bulider可以有多个可变参数,构造器就像方法一样,只能有一可变参数,因为builder利用单独的方法来设置每个参数,想要多少个就key有多少个, 该模式十分灵活,可以利用单个bulider对象,参数可以在创建对象时调整,也可以根据不同对象改变,buliderkey自动填充某些域,例如每次创建对象时自动增加序列号
不足:
为了创建对象,必须先创建它的构建器,虽然创建构建器的开销在实践中可能不那么明显,但是在某些注重性能的情况下,可能就成问题,Bulider模式比重叠构造器模式更加冗长因此只有很多参数的时候才使用.