8

私は最近、多数のオプション フィールドを持つオブジェクトを作成するJoshua Bloch のビルダー パターンを学びました。私はそのようなものを何年も使用してきましたが、Bloch の本で提案されるまで、内部クラスを使用したことはありませんでした。大好きです。

私は、別のスレッドが実際に構築される前にブライダーの構成を変更する可能性があることを理解しています (を使用build())。以下は、オプションでデータを再検証するビルダー クラスの例です。

だから私の質問はこれです:これが十分に堅牢な設計であると仮定すると、すべての値にデフォルトがある場合--このクラスがデフォルトを使用するための悪い選択であることを知っている--そして、すべての設定試行が検証される場合、この再チェックが必要ですか? ? 異なる場合がありますが、無効になることはありません。あれは正しいですか?

(この設計は扱いやすいですが、再検証が必要になる可能性があるため、確かに複雑です。正直なところ、私はマルチスレッドを使用したことはありませんが、マルチスレッドを使用する人がライブラリを使用できないようにしたくありません。)

アドバイスありがとうございます。

/**
   <P><CODE>java ReverifyBuilderInEnclosingCnstrXmpl</CODE></P>
 **/
public class ReverifyBuilderInEnclosingCnstrXmpl  {
   public static final void main(String[] igno_red)  {

      //Don't reverify
      ReverifyBuilderInEnclosingCnstrXmpl rvbdx = new ReverifyBuilderInEnclosingCnstrXmpl.Cfg().
         name("Big Bird").age(6).build();

      System.out.println(rvbdx.sName);
      System.out.println(rvbdx.iAge);

      //Do reverify
      rvbdx = new ReverifyBuilderInEnclosingCnstrXmpl.Cfg().
         reverifyInEnclosing().
         name("Big Bird").age(6).build();
   }

   public final String sName;
   public final int    iAge;
   /**
      <P>Create a new <CODE>ReverifyBuilderInEnclosingCnstrXmpl</CODE> with defaults.</P>
   **/
   public ReverifyBuilderInEnclosingCnstrXmpl()  {
      //Does not reverify. No need.
      this(new ReverifyBuilderInEnclosingCnstrXmpl.Cfg());
   }
   private ReverifyBuilderInEnclosingCnstrXmpl(ReverifyBuilderInEnclosingCnstrXmpl.Cfg rbdx_c)  {
      sName = rbdx_c.sName;
      iAge = rbdx_c.iAge;
      ReverifyBuilderInEnclosingCnstrXmpl.Cfg.zcibValues(rbdx_c, sName, iAge, "constructor");
   }
   public static class Cfg  {
      private String  sName   = null;
      private int     iAge    = -1;
      private boolean bReVrfy = false;
      public Cfg()  {
         //Defaults
         bReVrfy = false;
         name("Broom Hilda");
         age(127);
      }
      //Self-returning configuration...START
         //No way to unset.
         public Cfg reverifyInEnclosing()  {
            bReVrfy = true;
            return  this;
         }
         public Cfg name(String s_name)  {
            zcib_name(s_name, "name");
            sName = s_name;
            return  this;
         }
         public Cfg age(int i_age)  {
            zcib_age(i_age, "age");
            iAge = i_age;
            return  this;
         }
      //Self-returning configuration...END
      //Validate config...START
         public static final void zcibValues(ReverifyBuilderInEnclosingCnstrXmpl.Cfg rbdx_c, String s_name, int i_age, String s_clgFunc)  {
            try  {
               if(!rbdx_c.bReVrfy)  {
                  return;
               }
            }  catch(NullPointerException npx)  {
               throw  new NullPointerException("zcibValues: rbdx_c");
            }
            zcib_name(s_name, s_clgFunc);
            zcib_age(i_age, s_clgFunc);
         }
         public static final void zcib_name(String s_name, String s_clgFunc)  {
            if(s_name == null  ||  s_name.length() == 0)  {
               throw  new IllegalArgumentException(s_clgFunc + ": s_name (" + s_name + ") is null or empty.");
            }
         }
         public static final void zcib_age(int i_age, String s_clgFunc)  {
            if(i_age < 0)  {
               throw  new IllegalArgumentException(s_clgFunc + ": i_age (" + i_age + ") is negative.");
            }
         }
      //Validate config...END
      public ReverifyBuilderInEnclosingCnstrXmpl build()  {
         return  (new ReverifyBuilderInEnclosingCnstrXmpl(this));
      }
   }
}
4

2 に答える 2

5

アーキテクチャ レベルでのパターンを誤解しています。構築中のすべてのデータはローカル スレッドに関連付けられており、外部ハンドラには公開されません。ビルドが呼び出された瞬間、最終化されたパラメーターのセットが不変オブジェクトに渡されます。不変オブジェクトは、最初にコンストラクターでこれらのパラメーターの有効性を確認し、次に最終オブジェクトを返すか、例外をスローします。

ビルダー パラメーターをスレッド ローカルに保持している限り、スレッドの問題は発生しません。このルールに違反している場合は、自分が行っていることが正しいかどうか、および/またはよりきめ細かい方法でそれを解決するにはどうすればよいかを自問する必要があります。

したがって、例で異なるスレッドからビルダーを使用する必要がある場合、最も簡単で安全な方法は、静的に行うのではなく、新しいビルダー インスタンスを作成することです。パフォーマンスが心配な場合は、ThreadLocalが役に立ちます。

于 2014-01-06T11:14:32.797 に答える