3

今日の SO のどこかで、Java の不変オブジェクトに関する要点を説明するために使用された設計パターンを見ました。アイデアは、ユーザーが構築中に必要なプロパティの値を設定できるようにすることであり、次のようになります。

MyObject obj = new MyObject().name("Foo")
                             .height(5)
                             .width(3)
                             .color("blue")
                             .age(7);

このパターンに名前はありますか?

thisC++ では、各関数でポインターを返すことができることを知っています。Javaで同じ方法でどのように行われますか?

不変オブジェクトの場合、設定するプロパティごとにオブジェクトの新しいコピーを作成する必要がありますか?

4

4 に答える 4

3

ほぼこのスタイルで不変オブジェクトを構築したい場合は、ビルダーパターンが必要になる可能性があります。

これに表示される連鎖はFluent インターフェースとも呼ばれ、を返すことで実際に有効になりthisます。

構築中の実際のオブジェクトで流暢なインターフェイスを使用するコードでは、物事を設定するすべてのメソッドが実際にミューテーターである場合、オブジェクトは不変ではありません。これらのメソッドがすべて代わりに新しいオブジェクトを返す場合、this不変になる可能性があります。

于 2012-09-20T22:23:07.430 に答える
1

これは、他のユーザーのコメントに記載されているビルダー パターンではありません。

これはhttp://en.wikipedia.org/wiki/Fluent_interfaceで、似ていますが同じではありません。

最後の 2 つの質問は、変更可能な方法と変更不可能な方法の両方でこのパターンを実装できるため、ある程度相関していると思います。

変更可能に実装する場合は、メソッドごとに状態を変更し、これを返します。

public class UsefulThing {

   Integer state;

   public UsefulThing(Integer state) {
      this.state=state;
   }

   public UsefulThing alter(Integer newState) {
     state = newState;
     return this;
   }
}

不変の実装では、提供されたオブジェクトに基づいて新しいオブジェクトを作成し、それを返します。

public class UsefulThing {

   Integer state;

   public UsefulThing(Integer state) {
      this.state=state;
   }

   public UsefulThing alter(Integer newState) {

     return new UsefulThing(newState);
   }
}
于 2012-09-20T22:21:45.460 に答える
1

これはビルダー パターンの一種のように見えます (実際にはそうではありません)。

通常(あなたの例を使用し、それが不変であると仮定して)、次のようなパターンに従います。

public class MyObject {
    private final String name;
    private final int height;
    private final int width;
    private final String color;
    private final int age;

    private MyObject(Builder builder) { // Notice this is private
        name = builder.name;
        height = builder.height;
        width = builder.width;
        color = builder.color;
        age = builder.age;
    }

    // Getters

    public static class Builder {
        // Initialize these to defaults if you have any
        private String name;
        private int height;
        private int width;
        private String color;
        private int age;

        // Getters as usual

        // Every setter looks like this:
        public Builder setName(String name) {
            this.name = name;
            return this;
        }

        // Other setters

        public MyObject build() {
            return new MyObject(this);
        }
    }
}

それを使用するには:

MyObject obj = new MyObject.Builder()
        .setName("Foo")
        .setHeight(5)
        .setWidth(3)
        .setColor("blue")
        .setAge(7)
        .build();

ビルダーを再利用することもできます。

MyObject.Builder builder = new MyObject.Builder();
MyObject obj1 = builder
        .setName("Foo")
        .setHeight(5)
        .setWidth(3)
        .setColor("blue")
        .setAge(7)
        .build();
MyObject obj2 = builder
        .setName("Bar")
        .build();

ここで、は以外のすべてobj2と同じプロパティを持ちます。obj1name

これは通常、長いコンストラクターの代わりになります。また、すべての情報がすぐに利用できず、オブジェクトを作成するために必要なすべての場所で自分で変数の束を宣言したくないオブジェクトにも使用できます。最後の例から、同じプロパティで初期化したいオブジェクトがたくさんある場合に、それらのプロパティを何度も渡すことなく使用できることがわかります。

その結果、不変オブジェクトが作成されますが、コンストラクターや静的ファクトリ メソッドの場合のように、すべての変数を同時に設定/渡す必要はありません。

ここにいくつかの参照があります:

于 2012-09-20T22:29:08.157 に答える
0

ビルダーパターンの一例です。

より一般的な使用法は次のとおりです。

MyObject obj = new MyObjectBuilder().name("Foo").blah().build();

別個のビルダー クラスの使用に注意してください。

于 2012-09-20T22:19:39.327 に答える