当某个类的可选参数很多时,用构造器或静态工厂方法创建对象就显得相当麻烦。通常有这几种方式:
public class Person {
//必要参数
private final int id;
private final String name;
//可选参数
private final int age;
private final String sex;
private final String phone;
private final String address;
private final String desc;
public Person(int id, String name) {
this(id, name, 0);
}
public Person(int id, String name, int age) {
this(id, name, age, "");
}
public Person(int id, String name, int age, String sex) {
this(id, name, age, sex, "");
}
public Person(int id, String name, int age, String sex, String phone) {
this(id, name, age, sex, phone, "");
}
public Person(int id, String name, int age, String sex, String phone, String address) {
this(id, name, age, sex, phone, address, "");
}
public Person(int id, String name, int age, String sex, String phone, String address, String desc) {
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
this.phone = phone;
this.address = address;
this.desc = desc;
}
}
过多的构造器会使得代码非常臃肿,同时在创建对象时很容易因为参数列表的顺序错误导致难以察觉的问题。
public class Person {
//必要参数
private int id;
private String name;
//可选参数
private int age;
private String sex;
private String phone;
private String address;
private String desc;
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setSex(String sex) {
this.sex = sex;
}
public void setPhone(String phone) {
this.phone = phone;
}
public void setAddress(String address) {
this.address = address;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
这种模式弥补了重叠构造器模式的不足。创建实例很容易,这样产生的代码读起来也很容易,但也有缺陷:构造过程被分到了几个调用中,在构建过程中JavaBean可能处于不一致的状态,而且在这种模式下类不再是不可变状态,线程不安全。简而言之,JavaBean模式使构建对象的原子性遭到了破坏。
public class Person {
//必要参数
private final int id;
private final String name;
//可选参数
private final int age;
private final String sex;
private final String phone;
private final String address;
private final String desc;
private Person(Builder builder) {
this.id = builder.id;
this.name = builder.name;
this.age = builder.age;
this.sex = builder.sex;
this.phone = builder.phone;
this.address = builder.address;
this.desc = builder.desc;
}
public static class Builder {
//必要参数
private final int id;
private final String name;
//可选参数
private int age;
private String sex;
private String phone;
private String address;
private String desc;
public Builder(int id, String name) {
this.id = id;
this.name = name;
}
public Builder age(int val) {
this.age = val;
return this;
}
public Builder sex(String val) {
this.sex = val;
return this;
}
public Builder phone(String val) {
this.phone = val;
return this;
}
public Builder address(String val) {
this.address = val;
return this;
}
public Builder desc(String val) {
this.desc = val;
return this;
}
public Person build() {
return new Person(this);
}
}
}
此时Person是不可变的,所有的默认参数值都单独放在一个地方。builder的setter方法返回builder本身。