假如我們的一個實體類有很多的屬性值,但是這些屬性值又是可選的。如果我們遇到這樣的是類,如何設計出方便的實體類呢?
通常解決辦法一: 重疊構造器
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()); }