コンストラクターを使用する場合とgetInstance()メソッド(静的ファクトリメソッド)を使用する場合


84
  1. コンストラクターをいつどのように使用する必要があるか

    Foo bar = new Foo();
    
  2. そして、いつ、どのようにgetInstance()(静的ファクトリメソッド)を使用する必要がありますか

    Foo bar = Foo.getInstance();
    

これら2つの違いは何ですか?私はいつもコンストラクターを使用していましたが、getInstance()代わりにいつ使用する必要がありますか?


自分でクラスを書いていますか?そうでない場合、それを提供するものを何と呼んでいますか?
クリスB.

つまり、クラス自体の実装は、シングルトンパターンを実装しているということですよね?
zengr 2010

あなたは、呼び出し getInstance()、またはあなたがされているメソッドの書き込みと呼ばれるのgetInstance()
クリスB.

1
コンストラクタと静的ファクトリメソッドに関する質問の場合は、タイトルを明確にして変更することをお勧めします。
Pascal Thivent 2010

@zengr:update2に関しては、これは、静的メソッドに慣例に従って名前を付けなかったことが原因である可能性がありますFoo.newInstance()。これにより、名前を付ける必要があります。Foo.getInstance()クラスのシングルトンインスタンスを取得するための規則です。例を修正して、Foo.newInstance()代わりに使用する必要があります。
JRL 2010

回答:


96

質問は実際にはコンストラクターと静的ファクトリメソッドに関するものだと思いますが、誰もがシングルトンに焦点を合わせているようです。

これは実際には項目1です。JoshuaBlochによるEffectiveJavaのコンストラクターでは なく、静的ファクトリメソッドを検討してください

項目1:コンストラクターではなく静的ファクトリメソッドを検討する

クラスがクライアントにそれ自体のインスタンスを取得できるようにする通常の方法は、パブリックコンストラクターを提供することです。すべてのプログラマーのツールキットの一部である必要がある別の手法があります。クラスは、パブリック静的ファクトリメソッドを提供できます 。これは、クラスのインスタンスを返す単純な静的メソッドです。これはBoolean(プリミティブ型のボックス化されたプリミティブクラス boolean)の簡単な例です。このメソッドは、ブールプリミティブ値をBooleanオブジェクト参照に変換し ます。

public static Boolean valueOf(boolean b) {
    return b ? Boolean.TRUE : Boolean.FALSE;
}

静的ファクトリメソッドは 、デザインパターンのファクトリメソッドパターンと同じではないことに注意してください [Gamma95、p。107]。この項目で説明されている静的ファクトリメソッドには、デザインパターンに直接相当するものはありません。

クラスは、コンストラクターの代わりに、またはコンストラクターに加えて、静的ファクトリメソッドをクライアントに提供できます。パブリックコンストラクタの代わりに静的ファクトリメソッドを提供することには、長所と短所の両方があります。

利点(本を引用):

  • 静的ファクトリメソッドの利点の1つは、コンストラクタとは異なり、名前があることです。
  • 静的ファクトリメソッドの2番目の利点は、コンストラクタとは異なり、呼び出されるたびに新しいオブジェクトを作成する必要がないことです。
  • 静的ファクトリメソッドの3番目の利点は、コンストラクタとは異なり、戻り値の型の任意のサブタイプのオブジェクトを返すことができることです。
  • 静的ファクトリメソッドの4番目の利点は、パラメータ化された型インスタンスを作成する際の冗長性が軽減されることです。

短所(まだ本を引用しています):

  • 静的ファクトリメソッドのみを提供することの主な欠点は、パブリックコンストラクタまたは保護されたコンストラクタのないクラスをサブクラス化できないことです。
  • 静的ファクトリメソッドの2つ目の欠点は、他の静的メソッドと簡単に区別できないことです。

8
最後のものは多少軽減することができます。ファクトリメソッドを作成するときに明確にするために、ファクトリと呼ばれる静的内部クラスとさまざまなnewInstanceメソッドを含める傾向があります。それは私が過去の時間を探し回ることを節約しました。:)
リッチシューラー2010

@Qberticusファクトリメソッド専用の内部クラスは素晴らしいアイデアです。やってみます、thx。
Dave O.

確かに、クラスのコンストラクターは少なくともprotectedサブクラス化を許可する必要がありますが、クライアントコードは、静的ファクトリメソッドを呼び出すのではなく、新しいオブジェクトを作成してそのコンストラクターを呼び出すことで実際の利点が得られますか?連鎖コンストラクター呼び出しは意味的にはインスタンスメソッドであるように見えますが、「ユニタライズされたオブジェクトを作成してそのコンストラクターを呼び出す」というシーケンスは、静的ファクトリメソッド呼び出しと意味的に同等です。
スーパーキャット2014年

9

次の2つの質問を持っている:私は必要があるときに呼び出すgetInstance()方法、およびとき、私は必要があります作成するものを?

あなたがコールするかどうかを決定している場合getInstance()の方法、それは簡単です。クラスのドキュメントを読んで、いつ呼び出すべきかを確認する必要があります。例えば、NumberFormatコンストラクタを提供し、getInstance()方法。このgetInstance()メソッドは、ローカライズされたを提供しますNumberFormat。以下のためにCalendar、他方では、コンストラクタは保護されています。あなたはそれgetInstance()手に入れるために電話しなければなりません。

getInstance()メソッドを作成するかどうかを決定する場合は、何を達成しようとしているのかを決定する必要があります。あなたはどちらかしていない人は、(あなたが作成しているあなたのコンストラクタを呼び出したいシングルトンまたは工場)、または(のように、あなたは気にしないNumberFormat彼らは、発信者の便宜のためにいくつかのオブジェクトを初期化しているところ、上記)。


短編小説?getInstance()独自のコードでメソッドを作成することについて心配する必要はありません。それらが役立つ時が来れば、あなたは知っているでしょう。そして、一般に、クラスのコンストラクターを呼び出すことできれば、クラスがgetInstance()メソッドを提供している場合でも、おそらくそれを行うことになっています。


7

getInstanceメソッドの使用法:

ただし、ほとんどの場合、オブジェクトは単純なPOJOであり、パブリックコンストラクターの使用が最も実用的で明白なソリューションです。

U1:別のクラスからのgetInstance

別のクラスのインスタンスを返すには:

public class FooFactory {
    public static Foo getInstance() {
        return new Foo();
    }
}

NumberFormat.getInstanceメソッドは実際にのインスタンスを返すため、これを行いますDecimalFormat

U2:シングルトンの問題

シングルトンパターンは、オブジェクト指向プログラミングの利点の多くを制限します。シングルトンには通常、プライベートコンストラクターがあるため、それらを拡張することはできません。getInstanceメソッドを介してアクセスし、インターフェイスを参照しないため、別の実装と交換することはできません。


ファクトリパターンの場合、「createInstance」や「buildInstance」などの別のメソッド名の方がはるかに適していますが、それでも質問者が望む可能性のあるケースです(まだ少し曖昧で、宿題のように聞こえます)
jdehaan 2010

6

両方を使用できる場合は、実装が不十分なシングルトンパターンのように聞こえます

システム内にクラスのインスタンスを1つだけ持ち、コンストラクターをプライベートにする場合は、2番目のオプションを使用します。

最初のものを使用して、クラスの複数のオブジェクトを構築できるようにします。

しかし、あなたのクラスに両方の可能性を与えないでください。

シングルトンを使いすぎないように注意してください。システムにインスタンスが1つしかない場合にのみ使用してください。そうしないと、他のプロジェクトでクラスを再利用する可能性が制限されます。プロジェクトのどこからでもgetInstanceを呼び出せるのは興味深いことのように思えますが、実際にそのインスタンスを所有しているのは誰なのか、誰もいないのか、あるいはすべてなのかが不明確になります。プロジェクトにシングルトンがたくさんある場合は、システムの設計が不十分であることに間違いありません(通常)。シングルトンは注意して使用する必要があります。グローバル変数の場合と同じアドバイスが適用されます。


質問、少し混乱して、申し訳ありません更新
zengr

4
------>「ではない過剰使用シングルトンに注意してください」<------
バートバンHeukelom

1

通常のコンストラクターよりも静的ファクトリを常に好む1つのケースは、オブジェクトの構築が遅くなることがわかっている場合です。コンストラクターで単純な初期化を行いますが、重いものを作成する必要がある場合は、静的メソッドを使用して動作を文書化します。


0

シングルトンは悪です。それを取り巻く私が見た問題は、システムの再利用や拡張性に関するものではなく(それがどのように発生するかはわかりましたが)、それ以上に、シングルトンから生じるシステム。

シングルトンを使用する必要がある場合は、そのスコープが非常に狭いことを確認してください。つまり、シングルトンを認識しているシステム内の他のオブジェクトの数を慎重に制限してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.