ビルダーが独自のクラスファイルではなく内部クラスである必要があるのはなぜですか?


24

多くのBuilder Pattern例では、Builderビルドするオブジェクトの内部クラスを作成しています。

これは、Builderビルドの内容を示すため、ある程度意味があります。ただし、静的に型付けされた言語では、Builderビルドの内容がわかります。

一方、Builderが内部クラスである場合、の内部を見ずにビルドするクラス知る必要BuilderがありBuilderます。

また、ビルダーを内部クラスとして使用すると、外部クラスから参照できるため、インポートの数が減ります(気になる場合)。

そして、がBuilder同じパッケージ内にあるが、のような内部クラスではない実用的な例がありStringBuilderます。あなたはそれがそう名付けられているので、構築するBuilder 必要があることを知っていStringます。

そうは言ってもBuilder、内部クラスを作成する理由として考えられる唯一の正当な理由は、クラスのBuilder名前を知らず、命名規則に依存せずにクラスが何であるかを知っているということです。たとえば、もし私がStringBuilder内部クラスだったStringとしたら、おそらく私がそれよりも早く存在したことを知っていただろう(投機的)

Builder内なるクラスにする他の理由はありますか、それとも単に好みと儀式に帰着しますか?

回答:


30

これを行う理由は、内部クラス(Builder)が構築中のクラスのプライベートメンバーにアクセスできるようにするためだと思います。

http://docs.oracle.com/javase/tutorial/java/javaOO/nested.htmlから

非静的なネストされたクラス(内部クラス)は、プライベートであると宣言されている場合でも、囲んでいるクラスの他のメンバーにアクセスできます。

...

2つの最上位クラスAとBを考えてみましょう。Bは、そうでなければプライベートと宣言されるAのメンバーにアクセスする必要があります。クラスA内でクラスBを非表示にすることにより、Aのメンバーはプライベートと宣言され、Bはそれらにアクセスできます。

...

インスタンスのメソッドおよび変数と同様に、内部クラスはそれを囲むクラスのインスタンスに関連付けられ、そのオブジェクトのメソッドおよびフィールドに直接アクセスします。

これを説明するためのコードを次に示します。

class Example {

    private int x;

    public int getX() { return this.x; }

    public static class Builder {

        public Example Create() {
            Example instance = new Example();
            instance.x = 5; // Builder can access Example's private member variable
            return instance;
        }
    }
}

静的クラスであるBuilderには、関連付けられているExampleの特定のインスタンスがありません。ただし、Exampleのインスタンス(またはそれ自体が作成するインスタンス)を指定すると、Builderはそのインスタンスのプライベートメンバーに引き続きアクセスできます。


素晴らしい答えです、それは理にかなっています!ただし、ビルダーパターンには通常、静的な内部クラスがあり、外部クラスの静的なプライベートメンバーにのみアクセスできます。インスタンス化されたクラス用のビルダーがあれば、それはあらゆる種類の奇妙なものになります。
ナサニアル14年

1
@Nathanialではありません。プライベートインスタンス変数にもアクセスできます:ideone.com/7DyjDR
amon

1
@nathanial:はい。ただし、ビルダーはクラスを操作していません。ビルダー自体がインスタンス化したクラスのオブジェクトを操作しています。
ロバートハーヴェイ14年

@amonあなたがそこでしたことを見る。説明してくれてありがとう!
ナサニアル14年

具体的には、構築中のクラスのプライベートコンストラクターにビルダーがアクセスできるようにし、そのクラスが不変(すべてのフィールドがfinal)で、ビルダー経由でのみインスタンス化できるようにします。
マシューマクピーク

1

この場合、「すべき」はありません。別のクラス内でビルダーを定義するか、別個に作成することは、Builderパターンに直交します。多くの例では、1つの一貫性のあるファイルでコードを提示するのが便利なため、これを行います(プライベートメンバーにアクセスする場合でも、コンテキストに依存します)。それ以外の場合はお気軽に


「Javaでの方法ではないため」以外の理由で、この回答がなぜ反対票を投じられたかはわかりません。Builderパターンは、一連のパラメーターを取るコンストラクターのラッパーを提供します。コンストラクターがこれらのパラメーターを取る場合、Builderオブジェクトがプライベートメンバーにアクセスする必要はありません。
グレッグブルクハート
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.