前言
靜態工廠方法和構造器有一個共同的侷限性:當有大量可選參數時,方法的數量會不受控制。
當有大量可選參數時,開發者一般採用方法重載的方式來編寫構造器,面對大量的構造器調用者往往不知所云,尤其是參數類型相同的情況下,調用者往往要跟到源碼裏面去看才知道各個參數的意義。
面對這種情況,除了提供靜態工廠方法和構造器外,開發者往往還會將類設計成JavaBeans模式。
提供一個無參的構造方法,創建一個空對象,然後依次調用Set方法來設置屬性。
這麼做有以下缺點:
- 構造過程被分解,對象可能不一致
- 無法將類設計爲構造後不可變
類實例構造後仍然可變,意味着在多線程下可能出現數據安全問題,這需要調用者付出額外的精力去維護線程安全。
構建器
除了前面說的三種方法外,還有一種方法也應該被開發者考慮進來:構建器(Builder)。
使用構建器即可以保證安全性,也可以做到JavaBeans模式的可讀性,使得調用者代碼很好編寫,可選參數更好配置,得到一個流式的API。
例子
public class Car {
//類型
public final String type;
//顏色
public final String color;
//全景天窗 可選
public final Boolean panoramicSunroof;
//座位數 可選
public final Integer seat;
private Car(Builder builder){
this.type = builder.type;
this.color = builder.color;
this.panoramicSunroof = builder.panoramicSunroof;
this.seat = builder.seat;
}
public static class Builder{
private String type;
private String color;
private Boolean panoramicSunroof = false;//默認false
private Integer seat = 4;//默認4座
//必填屬性
public Builder(String type,String color){
this.type = type;
this.color = color;
}
//可選屬性
public Builder panoramicSunroof(Boolean panoramicSunroof){
this.panoramicSunroof = panoramicSunroof;
return this;
}
//可選屬性
public Builder seat(Integer seat){
this.seat = seat;
return this;
}
public Car build() {
return new Car(this);
}
}
@Override
public String toString() {
String s = "Car{" +
"type='" + type + '\'' +
", color='" + color + '\'' +
", panoramicSunroof=" + panoramicSunroof +
", seat=" + seat +
'}';
System.out.println(s);
return s;
}
}
客戶端構建實例
public class Client {
public static void main(String[] args) {
Car build = new Car.Builder("拖拉機", "騷紅").panoramicSunroof(true).seat(2).build();
build.toString();
}
}