对于一个参数有多个的构造器的类,程序员一向习惯采用重叠的构造器模式。
public class Person {
private String Id;
private String name;
private String address;
public Person(String id) {
Id = id;
}
public Person(String name, String address) {
super();
this.name = name;
this.address = address;
}
public Person(String id, String name, String address) {
Id = id;
this.name = name;
this.address = address;
}
}
重叠构造器模式可行,但是当有许多参数的时候,客户端代码会很难编写。并且难以阅读。遇到许多构造器参数的时候,还有第二种代替办法,即JavaBean模式(现在这种模式可以说是非常流行了)。在这种模式下,调用一个无参构造器来创建对象,然后调用setter方法来设置每个必要的参数。以及每个相关的可选参数:
public class Person {
private String Id;
private String name;
private String address;
public Person() {
super();
}
public String getId() {
return Id;
}
public void setId(String id) {
Id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
这样的话,我们每次用那个无参的构造器,然后想设置哪个变量就设置哪个。但是JavaBeans模式自身有着很严重的缺点。因为构造过程被分到了几个调用中。在构造过程中JavaBean可能处于不一致的状态。类无法仅仅通过检验构造器参数的有效性来保证一致性。
幸运的是,还有第三种替代方法,既能保证像重叠构造器模式那样的安全性,也能保证像JavaBeans模式那么好的可读性。这就是Builder模式。不直接生成想要的对象,而是让客户端利用所有必要的参数调用构造器,得到一个builder对象。然后客户端在builder对象上嗲用类似于setter的方法,来设置每个相关的可选参数。最后,客户端调用无参的builder方法来生成不可变的对象。这个builder是它构建器的类的静态成员类。
public class Person {
private String Id;
private String name;
private String address;
public static class Builder{
//所必须的参数
private final String Id;
//可选的参数
private String name = "";
private String address = "" ;
public Builder(String id){
this.Id = id;
}
public Builder name(String name){
this.name = name;
return this;
}
public Builder address(String address){
this.address = address;
return this;
}
public Person build(){
return new Person(this);
}
}
private Person (Builder builder){
this.Id = builder.Id;
this.name = builder.name;
this.address = builder.address;
}
}
调用:
Person person = new Person.Builder("100").address("ss").name("ss").build();
简而言之,如果类的构造器或者静态工厂中具有多个参数,设计这种类时,Builder模式就是种不错的选择,特别是当大多数参数都是可选的时候,与使用传统的重叠构造器模式相比,使用Builder模式的客户端代码将更易于阅读和编写,构造器也比JavaBeans更加安全。