web-dev-qa-db-ja.com

要素を条件付きで含むビルダー

オプションのパラメーターを使用してBuilderをよりエレガントに実行できるのではないかと思っていました。

私が持っているもの:名前、ID、年齢を持つオブジェクト。

年齢を含めるための複雑な条件があり、その条件の成功時にビルダーに送信したいのですが、1つのパラメーターを持つエレガントな1つのライナーにしたいと思います。

私がこれまでに持っているもの:

 Builder.name("name").id("id").age(age, complexCondition).build();

または

 Builder builder = Builder.name("name").id("id");
 if(complexCondition){
     builder.age(age);
 }

より良いオプションはありますか?すべての複雑な条件チェックのために、オーバーエンジニアリングビルダーやオーバーコーディングをせずに、問題が発生している状態を解決したいと思います。

upd:私が探しているのは、以下のないソリューションです:

a)complexChecksまたはbooleansをビルダーに渡す-定義によるチェックの仕事ではありません

b)ビルダーを呼び出すメソッド内の条件チェックごとに3行を追加しない

14

私の答えはそれをシンプルに保つことです。ビルダーの責任は、オブジェクトを構築することです。条件を評価するための複雑なDSLを提供しないこと。したがって、2番目のスニペットは完全に問題ありません。

ビルダーへの呼び出しとインターレースされた多数のifチェックによるコードの過負荷を避けるために必要なのは、これらのチェックのコードをメソッドに抽出することです。だからあなたはから行くことができます

Builder builder = Builder.name("name").id("id");
if (complexCondition) {
    builder.age(age);
}

Integer age = null; // or whatever other default value you want
if (complexCondition) {
    age = somethingElse;
}
Builder builder = Builder.name("name").id("id").age(age);

そして最後に、最初の4行をメソッドに抽出して年齢を計算し、年齢を返します。

Builder builder = Builder.name("name").id("id").age(computeAge());

私は個人的には次のようにインデントすることを好みます。これにより、IMOにより、読みやすくなり、デバッグが容易になります。

Builder builder = Builder.name("name")
                         .id("id")
                         .age(computeAge());
7
JB Nizet

まあ、メソッド呼び出しごとに1つの引数が必要な場合は、

_Builder.name("name").id("id").age(age, complexCondition).build();
_

_Builder.name("name").id("id").age(age).ageCondition(complexCondition).build();
_

complexConditionを_Predicate<Something>_(ここでSomethingは条件の評価に使用されるあるタイプのインスタンスです)にすることを検討することをお勧めします。このように、Builderbuild()を呼び出すと、年齢パラメーターが指定されている場合にのみ、複雑な条件が評価されます。

buildメソッドは次のようになります。

_public SomeClass build() {
    SomeClass obj = new SomeClass();
    obj.setName(name);
    if (age != null && someCondition != null && someCondition.test(something)) {
        obj.setAge(age);
    }
    return obj;
}
_

somethingがどうなるかわかりません。それはあなたの複雑な状態の性質に依存します。

または、条件をオプションにする場合:

_public SomeClass build() {
    SomeClass obj = new SomeClass();
    obj.setName(name);
    if (age != null) {
        if (someCondition != null)) {
            if (someCondition.test(something)) {
                obj.setAge(age);
            }
        } else {
            obj.setAge(age);
        }
    }
    return obj;
}
_
1
Eran