2016-07-03 10 views
4

、著者はビルダーを使用しているパラメータに不変条件を課すことについては、次の点に言及:ビルダーパターンの検証 - 効果的なJavaの(第2版)の項目2に有効ジャワ

彼らがコピーした後にチェックすることが重要ですビルダーからオブジェクトへのパラメータ、およびビルダフィールド(アイテム39)ではなくオブジェクトフィールドでチェックされていることを確認します。何らかの不変量が違反した場合、ビルドメソッドはIllegalStateExceptionをスローする必要があります(Item 60)。

これは、ビルドメソッドがターゲットオブジェクトを作成した後、必要な検証のために検証ルーチンに渡す必要があることを意味しますか?

また、誰かがこの背後にある理由を説明できますか?

+1

オブジェクトにコピーされた後にビルダーフィールドが変更される可能性があります。つまり、ビルダーは「有効」オブジェクトを作成する状態に置くことができます。 「無効な」オブジェクトが作成されていました。 –

+0

申し訳ありませんが、これを正しく理解すればわかりません。ビルダーは、新しい .Builder.setter1()。setter2。()。build()という名前で作成されます。どのように他のスレッドがこの特定のBuilderオブジェクトの参照を取得することができますか? –

+0

その場合、それはできませんでした。しかし、一般にスレッド間で共有されるビルダーインスタンスを停止するものは何もありません。 –

答えて

3

オブジェクトの検証は、ビルダーを使用したオブジェクト作成の不可欠な部分です。検証を行う別のルーチンを持つことはできますが、そのような分離は必要ありません。検証コードはビルドを行う関数の一部である可能性があります。言い換えれば、あなたはこの

TargetObject build() { 
    TargetObject res = new TargetObject(); 
    res.setProperty1(); 
    res.setProperty2(); 
    validate(res); // This call may throw an exception 
    return res; 
} 

void validate(TargetObject obj) { 
    if (...) { 
     throw new IllegalStateException(); 
    } 
} 

またはこれを行うことができます。

TargetObject build() { 
    TargetObject res = new TargetObject(); 
    res.setProperty1(); 
    res.setProperty2(); 
    if (...) { 
     throw new IllegalStateException(); 
    } 
    return res; 
} 

重要なことは、検証が、後に、前ではなく、対象物の建設を行われることです。つまり、ビルダの状態ではなく、オブジェクトの状態を検証する必要があります。

+0

もう一つの重要なことは、ビルダーではなく、検証するオブジェクトであるということです。なぜなら、それは有効なものでなければならないものだからです。 –

3

ビルダーのbuild()メソッドは、通常、ビルドしているクラスのプライベートコンストラクターを呼び出します。そのため、ビルダーは通常、静的ネストされたクラスとして実装されているため、プライベートコンストラクターにアクセスできます。コンストラクタは検証が行われる場所です。ビルダーパターンを使用していない場合でも、作成時にオブジェクトが有効な状態にあることをコンストラクターが保証します。また、フィールドがコピーされている間にビルダーが変更される可能性があるため、コンストラクターは防御コピー(EJアイテム39)を作成し、新しいオブジェクトのフィールドであるではなく、ビルダーのフィールドを検証する必要があります。

関連する問題