web-dev-qa-db-ja.com

静的メソッドの代わりにシングルトンを使用する理由

ヘルパー/ユーティリティクラスに関するこれらの簡単な質問に対する良い答えを見つけたことがありません。

静的メソッドを使用する代わりに、シングルトン(ステートレス)を作成するのはなぜですか?

オブジェクトに状態がない場合、オブジェクトインスタンスが必要なのはなぜですか?

85

多くの場合、シングルトンは、ある種のグローバル状態をアプリケーションに導入するために使用されます。 (正直に言うと、本当に必要以上に頻繁ですが、それはまた別のトピックです。)

ただし、stateless singletonでさえ有用な場合がいくつかあります。

  • 近い将来、状態を拡張する予定です。
  • 特定のtechnical理由のためにobject instanceが必要です。
    例:C#lockまたはJava synchronizedステートメントの同期オブジェクト。
  • 継承が必要です。つまり、同じインターフェースで異なる実装を使用して、シングルトンを別のシングルトンに簡単に置き換えることができるようにする必要があります。
    例:Java)のToolkit.getDefaultToolkit()メソッドは、正確なタイプがシステムに依存するシングルトンを返します。
  • 必要なのは、 sentinel値のreference equalityです
    例:DBNull.Value C#で。
76
Heinzi

静的メソッドクラスの代わりにステートレスシングルトン、つまり Dependency Injection が使用されている場合があります。

直接使用しているユーティリティ関数のヘルパークラスがある場合、非表示の依存関係が作成されます。誰がどこで使用できるかを制御できません。ステートレスシングルトンインスタンスを介して同じヘルパークラスをインジェクトすると、使用する場所と方法を制御し、必要に応じて置換/モック/などを行うことができます。

それをシングルトンインスタンスにすることで、必要以上の種類のオブジェクトを割り当てないようにします(必要なのは1つだけなので)。

37
tzaman

実際、私はここで言及されていない別の答えを見つけました:静的メソッドはテストするのが難しいです。

ほとんどのテストフレームワークは、インスタンスメソッドのモックに適していますが、その多くは静的メソッドのモックを適切に処理しません。

15

ほとんどのプログラミング言語では、クラスには多くの型システムが含まれていません。クラスは、その静的メソッドと変数とともにオブジェクトですが、多くの場合、インターフェイスを実装したり、他のクラスを拡張したりすることはできません。そのため、別のタイプのサブタイプにできないため、多態的に使用することはできません。たとえば、他のクラスのいくつかのメソッドシグネチャに必要なインターフェイスIFooableがある場合、クラスオブジェクトStaticFooIFooableの代わりに使用できませんが、FooSingleton.getInstance()は可能です(FooSingletonIFooableを実装すると仮定)。

ハインジの答えについてコメントしたように、シングルトンはインスタンス化を制御するパターンであることに注意してください。 new Class()Class.getInstance()に置き換えます。これにより、Classの作成者はインスタンスをより詳細に制御でき、不必要なインスタンスの作成を防ぐことができます。シングルトンは、ファクトリパターンの非常に特殊なケースであり、そのように扱う必要があります。一般的な使用法は、グローバルレジストリを単に意図的に使用することはできませんので、むしろグローバルレジストリの特殊なケースになります。

グローバルヘルパー関数を提供する予定の場合、静的メソッドは問題なく機能します。クラスはクラスとして機能するのではなく、名前空間として機能します。高い凝集力を維持するか、最も奇妙なカップリングの問題が発生する可能性があります。

グリーツ
back2dos

6
back2dos

どちらを使用するかにはトレードオフがあります。シングルトンには状態がある場合とない場合があり、オブジェクトを参照します。状態を保持せず、グローバルアクセスにのみ使用される場合は、これらのメソッドがより高速になるため、静的が優れています。しかし、オブジェクトとOOPコンセプト(継承ポリモーフィズム)を利用したい場合は、シングルトンの方が優れています。

たとえば、Java.lang.RuntimeはJavaのシングルトンクラスです。このクラスにより、JVMごとに異なる実装が可能になります。実装はJVMごとに1つです。このクラスが静的だった場合、JVMに基づいて異なる実装を渡すことはできません。

このリンクは本当に役に立ちました: http://javarevisited.blogspot.com/2013/03/difference-between-singleton-pattern-vs-static-class-Java.html

それが役に立てば幸い!!

4
Atihska

私にとっては「シングルトンを使用したいオブジェクト状態、静的メソッドを使用したい関数」

それはあなたが望むものに依存します。オブジェクトの状態(たとえば、nullの代わりにNull状態のようなポリモーフィズム、またはデフォルトの状態)が必要な場合は常に、関数が必要なときに静的メソッドが使用します(入力を受信して​​出力を返す) 。

シングルトンの場合には、インスタンス化後は常に同じ状態になることをお勧めします。クローン化することも、設定する値を受け取ることもできません(たとえば、Javaのpropertiesファイルからの静的構成を除きます)。

追伸これら2つのパフォーマンスはミリ秒単位で異なるため、最初にArchitectureに注目してください。

2
Toomtarm Kung

シングルトンはステートレスではなく、グローバルな状態を保持します。

シングルトンを使用することで考えられるいくつかの理由は次のとおりです。

  • メモリリークを回避するには
  • データベース接続などのアプリケーションのすべてのモジュールに同じ状態を提供するには
1
Indigo Praveen