2011-02-01 8 views

答えて

11

GoFパターンは、複数のコンストラクタによって追加された不要な複雑さの問題を「改訂されたビルダー」がターゲットにしている間に、ビルダーを変更することによって異なる結果を得ることができるように、だから、GoFパターンは抽象化についてのものであり、修正されたパターンはシンプルさ(IMO)に関するものです。

http://en.wikipedia.org/wiki/Builder_patternhttp://rwhansen.blogspot.com/2007/07/theres-builder-pattern-that-joshua.htmlの例を見てください。かなり明確になるはずです。

10

メモMikko's answerHansen's exampleにはいくつかの問題があります - あるいは、少なくとも、私はブロッホのバージョンが優れていると思いますが、少なくともブロッホのバージョンとの違いがあります。

は具体:

まず、WidgetのフィールドはなくWidgetコンストラクタよりもBuilder.build()に設定され、したがってない(できず)finalWidgetは不変であると言われていますが、後で別のプログラマーが来てセッターを追加するのを妨げるものはありません。

第2に、Hansenのビルドメソッドのコメントには、「作成前の検証がここにあります」というコメントがあります。ブロッホ(EJ 2ED P.15)は言う:

[不変式]はオブジェクトにビルダーからパラメータをコピーした後にチェックすることが重要である、と彼らはではなく、オブジェクトフィールドにチェックすることビルダー項目(項目39)。

アイテム39(P 185)に反転する場合は、推論を参照してください。

[これ]は、間の「脆弱性の窓」の間に別のスレッドからのパラメータの変化に対して、クラスを保護パラメータがチェックされた時刻とコピーされた時刻。 Widget

フィールドは不変であり、任意の守備のコピーを必要としませんが、それにもかかわらず、それは、誰かが一緒に来て、後でDate配列やあるいは何らかの可変Collectionを追加する場合には、単に正しいパターンに固執する方が安全です。 (それはまたbuild()への呼び出しの途中でBuilderを修正し、別のスレッドから保護しますが、それはおそらく最高のちょうどBuilder sはスレッド間で共有されていないことを確認していますので、それは安全性のかなり狭いウィンドウです。)

AよりBlochlikeのバージョンは次のようになります。

public class Widget { 
    public static class Builder { 
     private String name; 
     private String model; 
     private String serialNumber; 
     private double price; 
     private String manufacturer; 

     public Builder(String name, double price) { 
      this.name = name; 
      this.price = price; 
     } 

     public Widget build() { 
      Widget result = new Widget(this); 

      // *Post*-creation validation here 

      return result; 
     } 

     public Builder manufacturer(String value) { 
      this.manufacturer = value; 
      return this; 
     } 

     public Builder serialNumber(String value) { 
      this.serialNumber = value; 
      return this; 
     } 

     public Builder model(String value) { 
      this.model = value; 
      return this; 
     } 
    } 

    private final String name; 
    private final String model; 
    private final String serialNumber; 
    private final double price; 
    private final String manufacturer; 

    /** 
    * Creates an immutable widget instance. 
    */ 
    private Widget(Builder b) { 
     this.name = b.name; 
     this.price = b.price; 
     this.model = b.model; 
     this.serialNumber = b.serialNumber; 
     this.manufacturer = b.manufacturer; 
    } 

    // ... etc. ... 
} 

すべてWidgetのフィールドは今finalであり、すべてが建設後に検証されます。

+0

あなたの例では、偽の(または不足している、不安定な)プロパティを持つBuilderのインスタンスを作成し、「新しいウィジェット(myBogusBuilder)」を呼び出し、ウィジェットの「不安定な」インスタンスになることは許されませんか? (例えば、build()メソッドでしかチェックしていないので、値が少なくとも "1"以上であることを検証しないでください) – Rafa

+0

ウィジェットコンストラクタがpublicであってもプライベートだとしたら、それを(クラスの外から)呼び出す唯一の方法は、build()です。 –

+1

ああ、真;気づかなかった(私の眼鏡を見直すつもり...)。ありがとう:) – Rafa

関連する問題