2017-07-19 86 views
0

我最近閱讀了Effective Java,發現Builder Pattern(item#2)非常有趣。 不過,我有一個問題:我們爲什麼要建立一個靜態的建設者,當我們能做到這一點:以有效的Java去除Builder類型的Builder類

// JavaBeans Pattern 
public class NutritionFacts { 

private int servingSize; 
private int servings; 
private int calories; 
private int fat; 

public NutritionFacts() { 
} 

public NutritionFacts servingSize(int val) { 
    this.servingSize = val; 
    return this; 
} 

public NutritionFacts servings(int val) { 
    this.servings = val; 
    return this; 
} 

public NutritionFacts calories(int val) { 
    this.calories = val; 
    return this; 
} 

public NutritionFacts fat(int val) { 
    this.fat = val; 
    return this; 
} 

} 

//usage 
NutritionFacts nf = new NutritionFacts().servingSize(5).servings(4).calories(3).fat(1); 

在這樣做時,我們可能會避免創建2個實例。

你能解釋一下這個方法有什麼問題嗎?

+2

另一點:建設者模式在項目中經常被濫用。如果你所做的只是每次調用每個setter,你就不應該使用builder模式。只有在有多種方法來構造一個對象時,纔有用,也許有可選的部分,並且要確保它是以有效的方式構造的。我看過人們爲每個POJO寫了一個毫無意義的構建器的次數...... :( –

+0

@MrSpoon這不是真的 - 有一個構建器是完全合理的,你期望調用者調用每個方法*,如果它有助於可用性或可讀性*。例如,一個構造函數使用相同類型的幾個參數很容易被濫用,而構建器模式使得每個參數都是顯式的。 – dimo414

回答

3

A Builder允許抽象施工過程。

假設你想讓你的NutritionFacts成爲一個不可變的類。在這種情況下,Builder可以提供所有setter,並最終調用一個私有構造函數,它將所有這些構造函數(未設置的構造函數充滿合理的缺省值),而類本身不提供任何setter。

另一點是您可能想對值集進行一些驗證,特別是值之間的關係。構建器模式將始終包含一個可以執行此操作的方法build()

在你提供的例子中,它確實相當於在Builder或類中有setter方法。

2

在每一步你都有一個不完整的對象。生成器可以驗證對象,並以這種方式保護人們免於濫用你的課程。