Effective Java 第2條:遇到多個構(gòu)造器參數(shù)時要考慮使用構(gòu)建器
三種創(chuàng)建對象的方式。
目錄
- 重疊構(gòu)造器
- JavaBeans
- 構(gòu)建器
Builder
#重疊構(gòu)造器
/**
* Create By IntelliJ IDEA.
*
* @Author: Cheng
* @Date: 2017/10/30
* @Time: 19:21
* <p>
* 層疊構(gòu)造器
*/
public class User {
private String name; // required
private String password; // required
private int id; // optional
private String email; // optional
private String phone; // optional
private String address; // optional
public User(String name, String password, int id, String email, String phone, String address) {
this.name = name;
this.password = password;
this.id = id;
this.email = email;
this.phone = phone;
this.address = address;
}
public User(String name, String password) {
this(name, password, -1, null, null, null);
}
public User(String name, String password, int id) {
this(name, password, id, null, null, null);
}
public User(String name, String password, int id, String email) {
this(name, password, id, email, null, null);
}
public User(String name, String password, int id, String email, String phone) {
this(name, password, id, email, phone, null);
}
// 不提供 setter 方法,該對象就是不可變的了。
}
提供第一個只有必要參數(shù)的構(gòu)造器,第二個構(gòu)造器有一個可選參數(shù),第三個有兩個可選參數(shù),依次類推,最后一個構(gòu)造器包含所有可選參數(shù)。
重疊構(gòu)造器模式可行,但是當有許多參數(shù)的時候,客戶端代碼會很難編寫,并且依然較難閱讀。
參數(shù)一多起來不閱讀文檔將很難理解創(chuàng)建對象該傳什么參數(shù) 或者將參數(shù)順序搞亂
#JavaBeans
/**
* Create By IntelliJ IDEA.
*
* @Author: Cheng
* @Date: 2017/10/30
* @Time: 19:21
* <p>
* JavaBeans
*/
public class User {
private String name; // required
private String password; // required
private int id; // optional
private String email; // optional
private String phone; // optional
private String address; // optional
public User(String name, String password) {
this.name = name;
this.password = password;
}
// 省略getter and setter方法。
}
JavaBeans模式彌補了重疊構(gòu)造器的不足。說的明白點,就是創(chuàng)建實例很容易,這樣產(chǎn)生的代碼讀起來也很容易 get set
但是JavaBeans模式有一個缺點。因為構(gòu)造過程被分到了幾個調(diào)用中,在構(gòu)造過程中JavaBean可能處于不一致的狀態(tài),也就是說,JavaBean是非線程安全的。
JavaBeans模式阻止了把類做成不可變的可能。set
#構(gòu)建器 Builder
/**
* Create By IntelliJ IDEA.
*
* @Author: Cheng
* @Date: 2017/10/30
* @Time: 18:34
* <p>
* 構(gòu)建器模式
*/
/**
* 用戶類
*
* 帳號和密碼必須輸入
* id不賦值表示未存入數(shù)據(jù)庫
* 郵箱、手機、地址為選填項
*/
public class User {
private String name; // required
private String password; // required
private int id; // optional
private String email; // optional
private String phone; // optional
private String address; // optional
/**
* 構(gòu)造方法傳入構(gòu)造器
* @param builder
*/
private User(Builder builder) {
this.id = builder.id;
this.name = builder.name;
this.password = builder.password;
this.email = builder.email;
this.phone = builder.phone;
this.address = builder.address;
}
/**
* User類的構(gòu)造器
* 選填屬性設(shè)置默認值
*
* 必須傳入的屬性由構(gòu)造器傳入設(shè)置
* 選填屬性由方法設(shè)置
*/
public static class Builder {
private String name;
private String password;
private int id = -1;
private String email = "未設(shè)置";
private String phone = "未設(shè)置";
private String address = "未設(shè)置";
public Builder(String name, String password) {
this.name = name;
this.password = password;
}
/**
* 返回的是建造器對象
* @param email
* @return
*/
public Builder setEmail(String email) {
this.email = email;
return this;
}
public Builder setPhone(String phone) {
this.phone = phone;
return this;
}
public Builder setAddress(String address) {
this.address = address;
return this;
}
public User build() {
return new User(this);
}
}
// 不提供 setter 方法,該對象就是不可變的了。也就是說,保證了同步性。
}
擁有重疊構(gòu)造器模式的安全性,也能保證JavaBean模式那么好的代碼可讀性。這就是 Builder 模式的一種形式。
不直接生成想要的對象,而是讓客戶端利用所有必要的參數(shù)調(diào)用構(gòu)造器,得到一個
builder 對象。然后客戶端在 builder 對象上調(diào)用類似 setter 的方法來設(shè)置可選參數(shù)。最后調(diào)用無參的 build 方法來生成不可變的對象。
這個 builder 是它構(gòu)建的類的靜態(tài)成員類。
注意 User 被設(shè)計成不可變的了,所有的默認參數(shù)值都單獨放在一個地方。builder 的 setter 方法返回 builder 本身,以便把調(diào)用鏈接起來。下面是客戶端代碼:
public static void main(String[] args) {
User user = new User.Builder("cheng", "********")
.setEmail("qq.com")
.setPhone("110")
.setAddress("HangZhou")
.build();
System.out.println(user);
}
builder 就像個構(gòu)造器一樣,可以對器參數(shù)強加約束條件。buld 方法可以檢驗這些約束條件。
public User build() {
// 校驗邏輯
return new User(this);
}
不足
- 比起另外兩種創(chuàng)建模式,Builder 模式多創(chuàng)建了一個構(gòu)建器對象。
- 代碼量比重疊構(gòu)造器模式更加冗長。
#總結(jié)
如果類的構(gòu)造器中具有多個參數(shù),并且對安全有要求,設(shè)置這種類時,Builder 模式就是種不錯的選擇。