2013-03-23 51 views
1

我正在使用Builder模式來更容易地創建對象。但是,標準構建器模式示例不包含錯誤檢查,這是我的代碼中需要的。例如,Simulator對象中的accessibilitydemandMean陣列應具有相同的長度。代碼的簡要框架如下所示:帶有錯誤檢查的生成器模式:是否有可能/可取?

public class Simulator { 
    double[] accessibility; 
    double[] demandMean; 

    // Constructor obmitted for brevity 

    public static class Builder { 
     private double[] _accessibility; 
     private double[] _demandMean; 

     public Builder accessibility(double[] accessibility) { 
      _accessibility = accessiblity.clone(); 
      return this; 
     } 

     public Builder demandMean(double[] demandMean) { 
      _demandMean = demandMean.clone(); 
      return this; 
     } 

     // build() method obmitted for brevity 
    } 
} 

作爲另一示例,在一個推廣優化問題,有各種促銷車輛(例如傳單,顯示器)和促進模式,它們是一組促銷的車輛(例如沒有,只有傳單,只顯示,傳單和顯示)。當我創建Problem時,我必須定義可用的車輛集合,並檢查促銷模式是否使用這些車輛的一個子集,而不是其他一些無法使用的車輛,以及促銷模式不相同(例如, t兩個促銷模式都是「傳單專用」)。代碼的簡單框架如下圖所示:

public class Problem { 
    Set<Vehicle> vehicles; 
    Set<PromoMode> promoModes; 

    public static class Builder { 
     Set<Vehicle> _vehicles; 
     Set<PromoMode> _promoModes; 
    } 
} 

public class PromoMode { 
    Set<Vehicle> vehiclesUsed; 
} 

我的問題有以下幾點:

  1. 是否有解決這種情況的標準方法?
  2. 在調用build()方法時,應該在構造函數還是構建器中進行錯誤檢查?
  3. 爲什麼這是「正確」的方法?

回答

2

當您在創建對象時需要保持不變量時,如果任何參數違反了不變量,則停止構建。這也是一種快速失敗的方法。
當您擁有大量參數時,構建器模式有助於創建對象。
這並不意味着你不做錯誤檢查。
只想儘快拋出一個合適的RuntimeException作爲參數侵犯的對象不變

+0

這是有道理的。謝謝! – 2013-03-24 01:24:56

0

「正確」的做法真的取決於形勢 - 如果它是無效的構建不同大小的陣列,我會說這是更好地在施工中處理,無效狀態越早發現越好。

現在,如果您可以更改數組並放入不同的數組中 - 那麼在調用它時可能會更好。

1

您應該使用構造函數,因爲它更好地遵循單責任原則。製造商不負責檢查不變量。真正的工作是收集構建對象所需的數據。
此外,如果您決定稍後更改該類以具有公共構造函數,則不必移動該代碼。

你絕對不應該檢查setter方法中的不變量。這有幾個好處:
*您只需要檢查ONCE
*在例如您的代碼的情況下,由於您在不同的時間添加兩個數組,因此無法提前檢查不變量。您不知道您的用戶將添加它們的順序,因此您不知道應該使用哪種方法執行檢查。

除非您的構建器中的setter執行一些強烈的計算(這種情況很少出現 - 一般來說,如果需要進行某種計算,它應該在構造函數中發生),但對失敗沒有幫助早期「,尤其是像你這樣的流利建設者只使用1行代碼來構建對象,所以任何try塊都會圍繞整條線。

相關問題