2013-05-09 86 views
5

所以我一直在閱讀一些有效的Java!本書最鼓舞人心的部分之一是Bloch寫的關於「Builder」 - 類而不僅僅是POJO的不變對象/構建器部分。Java模型對象設計

注:我在這裏說的是模型對象:例如汽車

這是我以前寫的這些對象:

public class Car { 

    private String name; 

    public void setName(String name) { 
     this.name = name; 
    } 

    public String getName() { 
     return name; 
    } 
} 

現在,當你看到這樣的設計在許多方面不足,它需要的可變性,你必須構造與第一構造函數的對象,然後設置名字。

現在當然你可以使name字段最終並在構造函數中用作參數,但是如果你有一個大對象包裝例如一些SQL表,那麼你將會有一個醜陋的構造函數,像這樣:

public Car(int horsepowers, String name, String brand, int yearManufactured, 
    User owner, List<User> previousOwners) { 
    //Set the values 
} 

這在創建對象時變得不可讀,而這只是六個字段!

所以,布洛赫提出以下(含不變性)

public class Car { 

    public static class Builder { 

     private String name; 

     public Builder setName(String name) { 
      this.name = name; 
      return this; 
     } 

     public Car build() { 
      reeturn new Car(this); 
     } 
    } 

    private final String name; 

    private Car(Builder builder) { 
     name = builder.name; 
    } 

    public String getName() { 
     return name; 
    } 
} 

//Construction example 
Car car = new Car.Builder().setName("Speedy").build(); 

現在,這給了我們永恆!如果你有一些不是原始的或不可改變的物體,只需將它們複製到Builder的setter中,然後再將它們複製到Car的getters中。

但它很羅嗦,如果類足夠小,我一直在使用構造函數參數。 如果一個類需要一個可變字段,我只是讓該字段可變,如果該類有足夠的屬性(> 4東西)。

另一個問題是,當使用android並且該類具有例如Bitmap時,則必須返回實際的位圖並且不復制它,因爲這相當性能 - 昂貴。

我看過很多像這樣的問題,但我似乎無法在這個問題上找到很好的答案:在這些設計上是否有任何標準,它們的設計如何?什麼是好處/壞處?

在此先感謝!

編輯:

的問題是:

什麼是構造應該是一成不變的,用一個對象模型)少數領域和B)大的最好方式字段數?如何處理上面提到的Bitmap問題以及類似的問題?使某些領域可變?

對不起,模糊不清。

+0

我想'點Builder'是當你正在處理不可變具有一些必需和可選字段的對象。因爲你會將字段聲明爲'final'。所以它不適用於每個設計。 – Sam 2013-05-09 09:11:17

回答

4

Design Patterns本書是目前設計模式的alpha和歐米茄。但它並不是新的,但它似乎已經通過了時間的考驗。

您可以閱讀每個設計模式的詳細現實生活實例,它們如何相互關聯,如何以及何時使用它們以及每個設計模式的詳細解釋。 Builder模式當然包括在內。

至於回答你的問題,我可以提出我的意見,雖然他們當然不是權威。

我認爲,如果你有少量的字段,你可以使用構造函數。例如,如果您採取checkstyle,它將觸發超過7個參數的警告。

但是,如果你確實知道你會很快重構那個類,或者你將不得不擴展它,我認爲Builder模式更好,因爲它更容易重構。重構構造函數從不好玩。

如果你超過7個參數,我認爲Builder更好。我一直在廣泛使用當前的項目中使用它。

請注意,通過使用Builder模式,您不會說「好吧,我是一個不可變的對象生成器」。你說「好吧,我正在建立參數化對象」。因此,你的班級中有一組可變字段並不是問題。如果你的名字像ImmutableFooDTO那樣命名,那麼你添加可變字段會導致混淆。

因此,如果有一組不可變的字段,那麼將它們標記爲final並使用構造函數/構建器併爲可變元素提供setter。

+0

嗨!是的,我讀過一個Java的等價物,但這就是構建器模式,因爲你看到這有點少了。它並沒有真正回答這個問題。但謝謝你的迴應。 – 2013-05-09 09:11:43

+0

請再次看看你的問題:「這些設計是否有任何標準,它們的設計如何?有什麼好處/壞處?」我已經回答了你的問題。我在那裏看不到任何其他問號。 – 2013-05-09 09:14:02

+0

嗨,是的,我知道這個問題,我感謝你的迴應。但是這裏的問題是:*何時使用哪種模型:上面解釋的* Builder *或構造函數參數,如何處理不可變/可變字段等。我無法接受你的答案,只是因爲你鏈接到一本本本是工業「標準」的書,但仍然沒有涵蓋我在上面和我的問題中提到的所有方面。 – 2013-05-09 09:18:16

2

我輸入這個作爲「答案」,所以我有空間來解釋,但這只是對Adam Aroid開始的線程的評論。

Johan,首先我假設你正在討論Effective Java中的Item 2。

請注意,這裏呈現的是一種Builder模式Adam Aroid提到的形​​式。 Josh Bloch直接在有效Java中展示代碼之前就提到了這一點:「它是Builder模式的一種形式[Gamma95,p。97]。」他在後面提到了一種使用另一種模式的方法(來自同一本書):「一個建造者的參數已經設置好了,抽象工廠[Gamma95,p。87]。您提出的問題對於這裏的空間太寬泛了,我認爲最好的答案是Adam Aroid的答案,這需要一些研究,然後應用該研究來獲得一些經驗。我會投票亞當的回答了

+0

感謝信用。 – 2013-05-09 21:10:48

-1

與此代碼試試:

public static boolean isEmailValid(String email) { 

    boolean isValid = false; 

    String expression = "^[\\w\\.-][email protected]([\\w\\-]+\\.)+[A-Z]{2,4}$"; 
    CharSequence inputStr = email; 

    Pattern pattern = Pattern.compile(expression, Pattern.CASE_INSENSITIVE); 
    Matcher matcher = pattern.matcher(inputStr); 
    if (matcher.matches()) { 
     isValid = true; 
    } 
    return isValid; 
}