原文出自:http://www.cnblogs.com/parryyang/p/5696916.html
静态工厂和构造器有个共同的局限性:它们都不能很好地扩展到大量的可选参数。假如我们的一个实体类有很多的属性值,但是这些属性值又是可选的。如果我们遇到这样的是类,如何设计出方便的实体类呢?
通常解决办法一: 重叠构造器
public class User {
private String id; // id(必填)
private String name; // 用户名(必填)
private String email; // 邮箱(可选)
private int age; // 年龄(可选)
private String phoneNumber; // 电话(可选)
private String address; // 地址(可选)
public User(String id, String name) {
this(id, name, "qq.com", 0, "120", "广州");
}
public User(String id, String name, String email) {
this(id, name, email, 0, "120", "广州");
}
public User(String id, String name, String email, int age) {
this(id, name, email, age, "120", "广州");
}
public User(String id, String name, String email, int age, String phoneNumber) {
this(id, name, email, age, phoneNumber, "广州");
}
public User(String id, String name, String email, int age, String phoneNumber, String address) {
this.id = id;
this.name = name;
this.email = email;
this.age = age;
this.phoneNumber = phoneNumber;
this.address = address;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public String getEmail() {
return email;
}
public int getAge() {
return age;
}
public String getPhoneNumber() {
return phoneNumber;
}
public String getAddress() {
return address;
}
}
注:许多你不想设置的参数,但是还不得不为他们传递值通常解决办法二: JavaBean模式(调用一个无参构造器来创造对象,然后调用setter方法来设置每个必须的参数,以及每个相关的可选参数)
public class User {
private String id; // id(必填)
private String name; // 用户名(必填)
private String email; // 邮箱(可选)
private int age; // 年龄(可选)
private String phoneNumber; // 电话(可选)
private String address; // 地址(可选)public User() {
super();
}
public void setId(String id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setEmail(String email) {
this.email = email;
}
public void setAge(int age) {
this.age = age;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public void setAddress(String address) {
this.address = address;
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public String getEmail() {
return email;
}
public int getAge() {
return age;
}
public String getPhoneNumber() {
return phoneNumber;
}
public String getAddress() {
return address;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", email=" + email + ", age=" + age + ", phoneNumber="
+ phoneNumber + ", address=" + address + "]";
}
}
注:JavaBeans模式自身有着很严重的缺点。因为构造过程被分到几个调用中,在构造过程中JavaBean可能处于非一致的状态。JavaBeans模式阻止了把类做成不可变的可能,这就需要确保他的线程安全。
解决办法三: 构建器
public class User {
private String id; // id(必填)
private String name; // 用户名(必填)
private String email; // 邮箱(可选)
private int age; // 年龄(可选)
private String phoneNumber; // 电话(可选)
private String address; // 地址(可选)
public static class Builder{
private String id; // id(必填)
private String name; // 用户名(必填)
private String email; // 邮箱(可选)
private int age; // 年龄(可选)
private String phoneNumber; // 电话(可选)
private String address; // 地址(可选)
public Builder(String id, String name) {
super();
this.id = id;
this.name = name;
}
public Builder email(String email){
this.email = email;
return this;
}
public Builder age(int age){
this.age = age;
return this;
}
public Builder phoneNumber(String phoneNumber){
this.phoneNumber = phoneNumber;
return this;
}
public Builder address(String address){
this.address = address;
return this;
}
public User builder(){
return new User(this);
}
}
private User(Builder builder){
this.id = builder.id;
this.name = builder.name;
this.email = builder.email;
this.age = builder.age;
this.phoneNumber = builder.phoneNumber;
this.address = builder.address;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", email=" + email + ", age=" + age + ", phoneNumber="
+ phoneNumber + ", address=" + address + "]";
}
public String getId() {
return id;
}
public String getName() {
return name;
}
public String getEmail() {
return email;
}
public int getAge() {
return age;
}
public String getPhoneNumber() {
return phoneNumber;
}
public String getAddress() {
return address;
}
}
注:不直接生成想要的对象,而是让客户端利用所有必要的参数调用构造器(或者静态工厂),得到一个builder对象。然后客户端在builder对象上调用类似于setter的方法,来设置每个相关的可选参数。最后,客户端调用无参的build方法来生成不可变的对象。
测试代码
public static void main( String[] args ) { User user = new User.Builder(UUID.randomUUID().toString(), "parry").address("广州").builder(); System.out.println(user.toString()); }