静态工厂方法和构造器都有一个共同的缺点,都不能很好的扩展到大量的参数。
对于有多个参数时,我们一向习惯使用重叠构造器模式,在这种情况下,提供一个必填参数的构造器,第二个构造器带有一个可选参数,第三个构造器带有两个可选参数,以此类推,最后一个构造器包含所有参数:举个粒子:
public class Demo{
private String var1;
private String var2;
private String var3;
public Demo(String var1){
this(var1,"");
}
public Demo(String var1,String var2){
this(var1,var2,"");
}
public Demo(String var1,String var2,String var3){
this.var1 = var1;
this.var2 = var2;
this.var3 = var3;
}
}
public class Main{
public static void main(String[] args){
Demo demo = new Demo("setVar1");
demo = new Demo("setVar1","setVar2");
demo = new Demo("setVar1","setVar2","setVar3");
}
}
如果仅仅是这几个参数还不算大问题,但是随着参数的增加,很快就会变得失去控制。而且随着参数的增加,必须仔细的数着这些参数来确保传入值的顺序正确。如果出现顺序的颠倒,编译器可能不会报错,但是程序运行的结果却却可能天差地别,甚至会出现异常。
还有一种方式是通过JavaBean的setter方法来为每个值单独设值。
public class Demo{
private String var1;
private String var2;
private String var3;
public Demo(){
}
public Demo(String var1){
this(var1,"");
}
public Demo(String var1,String var2){
this(var1,var2,"");
}
public Demo(String var1,String var2,String var3){
this.var1 = var1;
this.var2 = var2;
this.var3 = var3;
}
public void setVar1(String var1){
this.var1 = var1
}
public void setVar2(String var2){
this.var2 = var2
}
public void setVar3(String var2){
this.var2 = var2
}
}
public class Main{
public static void main(String[] args){
Demo demo = new Demo();
demo.setVar1("setVar1");
demo.setVar2("setVar2");
demo.setVar3("setVar3");
}
}
这种模式在构造过程中,在多线程的情况下无法保证数据的一致性,需要符出额外的努力来确保线程安全。
有一种方案可以比较好的解决以上问题,既能保存重叠构造器模式的安全性,又能保证可读性,这就是建造者模式的一种体现,这种方式不直接生成对象,而是利用必要的参数调用构造器或者静态工厂方法,得到一个Builder对象,然后在Builder对象中调用类似于setter的方法,来设置可选参数,最后,调用无参的build方法来生成目标对象。build通常是他构建类的成员静态类。举个栗子:
public class Demo{
private String name;
private int age;
private Date time;
private String other;
public static class Builder{
private String name;
private int age;
private Date time;
private String other;
public Builder(String name,int age){ // 静态成员类
this.name = name;
this.age = age;
}
public Builder time(Date time){
this.time = time;
return this;
}
public Builder other(String other){
this.other = other;
return this;
}
public Demo build(){
return new Demo(this);
}
}
private Demo(Builder builder){
this.name = builder.name;
this.age = builder.age;
this.time = builder.time;
this.other = builder.other;
}
}
public class Main{
public static void main(String[] args){
Demo demo = new Demo.Builder("xiaowu",1).time(new Date()).other("love java").build();
}
}
与构造器相比,builder的优势在于,可以有多个可变参数,因为bulidre利用单独的方法来设置每一个参数,此外,构建器可以将多次调用某一个方法的参数集中到一个集合中。
builder的模式也有不足之处,为了创建对象,需要先创建构建器,虽然创建builder的开销在实践中不是很明显,但是在某些十分注重性能的情况下,可能就会有问题,而且builder比重叠构造器模式更加沉长,所以建议只有当参数超过4个及以上,或者将来可能需要更多的参数,就可以考虑使用builder模式。
简而言之,如果类的构造器或者静态工厂中有多个参数,设计这种类时,builder模式是一种不错的选择,与构造器相比,使代码更加易于阅读和编写,同时也比JavaBean模式更加安全。
网友评论