静的メソッドの代わりにシングルトンを使用するのはなぜですか?


92

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

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

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



2つの異なる言語について話し合っているので答えは異なる場合があるので、考えないでください。リンクのおかげで、Javaでは「モノステート」という用語を聞いたことがない
Sebastien Lorber

回答:


79

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

ただし、ステートレスシングルトンでさえも役立ついくつかのコーナーケースがあります。

  • あなたは予見可能な将来の状態でそれを拡張することを期待しています。
  • 特定の技術的な理由から、オブジェクトインスタンスが必要です。例:C#またはJava ステートメントの同期オブジェクト。
    locksynchronized
  • 継承が必要です。つまり、同じインターフェースで異なる実装を使用して、シングルトンを別のシングルトンに簡単に置き換えることができるようにする必要があります。
    例:Toolkit.getDefaultToolkit()Java のメソッドは、正確な型がシステムに依存するシングルトンを返します。
  • あなたはしたい参照の等価のためのセンチネル値を
    例:DBNull.ValueC#で。

27
私は+1を使用しますが、IMHOシングルトンはグローバルな状態を導入するために誤用されます。シングルトンの目的は、オブジェクトをグローバルに使用可能にすることではなく、オブジェクトが1回だけインスタンス化されるようにすることです。グローバルオブジェクトは必要悪です。本当に必要な場合を除いて、SomeSingleton.getInstance()。someMethod()がいたるところにあるため、一般的に高結合につながるため、それらを使用しないようにしてください。:)
back2dos

これは、複数のレンダーインスタンスではなく1つのレンダーインスタンスだけが必要なゲームや、一度に1つの接続しか存在できないセキュリティチャネルを設定するネットワークパイピングクラスを使用する場合に役立ちます。
Tschallacka

2
「あなたのシングルトンを簡単に交換する」という部分は、私の見解では最も重要なポイントです。残りは、静的クラスの実装にかなり近いです。
Teoman Shipahi 2016年

1
シングルトンは、合計/積のタイプなどのnull以外の有用なセンチネル値です。たとえば、オプションタイプではNone / Nothing値、コレクションタイプではEmpty値です。参照の等価性が必要なすべてであるため、ボーナスとして高速なし/空のテストを取得できます。
itsbruce

@itsbruce:あなたの例はシングルトンではありません:空のリストがListクラスの唯一の可能なインスタンスではなく、None値はOptionクラスの唯一の可能なインスタンスではありません。ただし、センチネル値シングルトンである例があり、私は自由に私の回答に1を追加しています。入力ありがとうございます!
ハインツィ

37

静的メソッドクラスの代わりにステートレスシングルトンが使用されるケース、つまりDependency Injectionのケースを見ることができました。

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

これをシングルトンインスタンスにすると、そのタイプのオブジェクトが必要以上に割り当てられないことが保証されます(必要になるのは1つだけなので)。


1
「あなたはそれを誰がどこで使うことができるかを制御することはできません。」なぜ誰かがそれを必要とするのでしょうか?
hagrawal 2015

1
テスト目的の@hagrawal、それを模擬できるはずです
Jemshit Iskenderov

15

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

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


2
しかし、Powermockはそうすることができるようです
Sebastien Lorber

6

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

ハインジの答えにコメントしたように、シングルトンはインスタンス化を制御するパターンであることに注意してください。これは、置き換えnew Class()Class.getInstance()の著者与える、Class彼は不必要なインスタンスの生成を防止するために使用できるインスタンス、より細かく制御します。シングルトンは、ファクトリパターンの非常に特殊なケースであり、そのように扱う必要があります。一般的な使用法は、グローバルレジストリの特別なケースではなく、グローバルレジストリをただ単に無用に使用するべきではないため、多くの場合悪い結果に終わります。

グローバルヘルパー関数を提供する場合は、静的メソッドが問題なく機能します。クラスはクラスとしてではなく、単なる名前空間として機能します。私は、高い凝集度を維持することをお勧めします。そうしないと、結局、奇妙な結合の問題が発生する可能性があります。

greetz
back2dos


4

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

例を考えてみましょう:java.lang.Runtimeはjavaのシングルトンクラスです。このクラスにより、JVMごとに異なる実装が可能になります。実装はJVMごとに1つです。このクラスが静的である場合、JVMに基づく異なる実装を渡すことはできません。

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

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


この答えは、現実の世界で具体的な例を含めるのに適しています。
systemovich 2016年

2

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

それはあなたが望むものに依存します。オブジェクトの状態(たとえばnull、の代わりにNull状態のような多態性、またはデフォルトの状態)が必要な場合は常に、シングルトンが適切な選択ですが、静的メソッドは関数が必要なときに使用します(入力を受け取ってから出力を返します)。

シングルトンの場合は、インスタンス化した後は常に同じ状態にすることをお勧めします。クローン可能であってはならず、設定する値も受け取りません(Javaのプロパティファイルなどのファイルからの静的構成を除く)。

PSこれら2つの間のパフォーマンスはミリ秒単位で異なるため、最初にアーキテクチャに焦点を当てます。


1

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

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

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

私は知っていますが、実際にはシングルトンは多かれ少なかれステートレスになる可能性があります...それがクラス属性を共有しない場合...
Sebastien Lorber
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.