3

私はビルダーパターンに非常に興味があり、頻繁に使用しますが、作成するビルダーが十分に優れているかどうかはわかりません。また、それらを使用できるすべての環境について疑問があります。これは、ビルダーを作成する方法の例です。

public class Person {

    private String name;
    private String secondName;
    private int age;

    public static class Builder {
        private boolean isBuilt;
        private Person person = new Person();

        private void check() {
            if (isBuilt) {
                throw new IllegalStateException(
                        "The object cannot be modified after built");
            }
        }

        public Builder withName(String name) {
            check();
            person.name = name;
            return this;
        }

        public Builder withSecondName(String secondName) {
            check();
            person.secondName = secondName;
            return this;
        }

        public Builder withAge(int age) {
            check();
            person.age = age;
            return this;
        }

        public Person build() {
            check();
            isBuilt = true;
            return person;
        }
    }

    @Override
    public String toString() {
        return "Name: " + name + "\nSecond name:" + secondName + "\nAge:" + age;
    }
}

簡単な使用例:

Person person = new Person.Builder()
        .withName("John")
        .withSecondName("Smith")
        .withAge(50)
        .build();
        System.out.println(person);

ここに私の疑問のいくつかがあります:

  • 本当に不変だと思いますか?いいえの場合、どうすれば改善できますか?
  • スレッドセーフについて。さて、これはおそらく私の主な疑問です。これは本当にスレッドセーフですか?私はインターネットで、クラスレベルの変数はfinalであり、コンストラクターを介して渡される必要があるという例を見ました。また、変数が揮発性として宣言された1つの例を見ました。あなたはそれについてどう思いますか?
  • このビルダーは、それを使用できるシナリオに関して何か制限があると思いますか?つまり、EJB、JSFバッキングBean、MDBのいずれかで呼び出されるか、JPAエンティティになるのが適切でしょうか...?
4

1 に答える 1

1

本当に不変だと思いますか?[...]これは本当にスレッドセーフですか?

コードのどの部分も不変ではありません。これはおそらくスレッドセーフを妨げるでしょう。つまり、クラスがバイナリ形式でスレッドセーフであるかどうかを宣言するのは非常に困難です。また、そもそもなぜスレッド間でビルダーインスタンスを共有するのかわかりませんが、コードサンプルの単純さに誤解を招く可能性があります。

スレッドセーフの達成を容易にするために、あなたBuilderはそれ自体が不変でなければなりません。これは、すべてwithXXX()のメソッドが新しい状態を表す新しいビルダーを返す必要があることを意味します。(これを行うにはおそらくもっと賢い方法がありますが、それは簡単なアプローチです。)

繰り返しになりますが、ビルダーをスレッドセーフにする必要があるかどうかはわかりません。ほとんどの場合、これらは非常に短い存続期間と可視範囲を持つオブジェクトです。それらを不変にするかどうかはユースケースによって異なりますが、部分的に満たされたビルダーを格納することもできますが、それもややまれです。with(ただし、名前が。で始まるメソッドとは対照的に、名前がインプレースでオブジェクトを変更しないことで始まるメソッドの方が主観的に直感的に見えますset。)

このビルダーは、それを使用できるシナリオに関して何か制限があると思いますか?

これは一般的に答えられませんが、Personオブジェクトを不変にし、したがってビルダーによってのみ構築可能にすると、それらはJPAエンティティとして使用できなくなります。私の推測では、JSFバッキングBeanも同様です。特定のオブジェクトを作成/管理するJavaフレームワークは、JavaBeansであると期待することがほとんどです。つまり、これらのオブジェクトは、リフレクションを介して引数なしのコンストラクターとプロパティセッターを呼び出すことで作成できます。

于 2013-02-10T23:47:45.053 に答える