遇到多個構造器引數時要考慮用構建器Bulider
靜態工廠和構造器有個共同的侷限性:他們都不能很好的擴充套件大量的可選引數,
比如包裝食品營養成分標籤,含量,卡路里,等等,有可能會超過20個可選域,對於這樣的類,應該用那種構造器或靜態方法來寫呢,
構造器:
程式設計師一般習慣採用過載構造器來實現,第一個構造器,提供一個必要引數,第二個構造器提供,一個必要引數,一個可選引數,依次類推.
public NutritionFacts(int servingSize){}
public NutritionFacts(int servingSize,int calories){}
public NutritionFacts(int servingSize,int calories,int fat){}
缺點
構造器呼叫通常需要許多本不想設定引數,但是不得不為他們傳遞值.隨著引數數目的增加,就很快失去了控制
javabean模式:
這種模式下呼叫一個午餐構造器來建立物件,然後呼叫setter方法來設定每個必要的引數,以及每個可選引數.
public class NutritionFacts{
private int servingSize=-1;
private int servings=-1;
private int calories=0;
...getter setter省略
}
優點:彌補了重疊構造器模式的不足,建立例項很容易,程式碼易讀性強
NutritionFacts cocaCola=new NutritionFacts();
cocaCola.setServingSize(22);
cocaCola.setServings(22);
...
缺點:
其構造過程中被分到幾個呼叫中,在構造過程中JavaBean可能處於不一致的狀態,這種失敗與包含錯誤程式碼,類無法僅僅通過檢驗構造器引數的有效性來保證一致性,試圖使用不一致狀態的物件,將會導致失敗,這種失敗與包含錯誤的程式碼大相徑庭,因此它除錯起來非常困難,另一點不足,JavaBean阻止了把類做成不可變類的可能,這就需要額外的努力來確保他的執行緒安全.
構建器模式:
public class NutritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate;
public static class Bulider{
private int servingSize;
private int servings;
private int calories=0;
private int fat=0;
private int sodium=0;
private int carbohydrate=0;
public Bulider( int servingSize,int servings) {
this.servings=servings;
this.servingSize=servingSize;
}
public Bulider calories( int var) {
this.calories=var;
return this;
}
public Bulider fat( int var) {
this.fat=var;
return this;
}
public Bulider sodium( int var) {
this.sodium=var;
return this;
}
public Bulider carbohydrate( int var) {
this.carbohydrate=var;
return this;
}
public NutritionFacts bulid() {
return new NutritionFacts(this);
}
}
private NutritionFacts(Bulider bulider) {
servings=bulider.servings;
servingSize=bulider.servingSize;
calories=bulider.calories;
fat=bulider.calories;
sodium=bulider.sodium;
carbohydrate=bulider.carbohydrate;
}
}
//客戶端測試
@Test
public void codeTest() {
NutritionFacts nutritionFacts=new NutritionFacts.Bulider(240, 8).
calories(100).sodium(33).carbohydrate(22).bulid();
}
優勢:
bulider可以有多個可變引數,構造器就像方法一樣,只能有一可變引數,因為builder利用單獨的方法來設定每個引數,想要多少個就key有多少個, 該模式十分靈活,可以利用單個bulider物件,引數可以在建立物件時調整,也可以根據不同物件改變,buliderkey自動填充某些域,例如每次建立物件時自動增加序列號
不足:
為了建立物件,必須先建立它的構建器,雖然建立構建器的開銷在實踐中可能不那麼明顯,但是在某些注重效能的情況下,可能就成問題,Bulider模式比重疊構造器模式更加冗長因此只有很多引數的時候才使用.