web-dev-qa-db-ja.com

シングルトンを使用する場合と静的クラスを使用する場合

私はこことStackOverflowでこれについて検索し、2つの違いを見つけました。

しかし、まだわかりませんどの場合にシングルトンが好まれ、どのような場合に静的クラスの使用を選択するか

(Javaのように「静的クラス」をサポートしない言語では、静的メソッドとフィールドのみを含むクラスを明確に参照しています)。

それぞれを選ぶ具体的な例を挙げて、その理由を説明してください。

34
Aviv Cohn

静的クラスが適切な場合は、関連する機能を収集したいが、オブジェクトの内部状態を必要としない場合です。例としては、JavaのMathクラスがあります。これには、特定のオブジェクトインスタンスのコンテキスト外でアクセスされる、関連する関数がすべて含まれています。アプリケーションの複数の場所で使用される一連の一般的なユーティリティ関数を1つのユーティリティクラスにグループ化する場合も、同様のことを行いました。

シングルトンはdoが実際のオブジェクト(独自の内部状態とすべてを持つ)を必要とし、システムをそのオブジェクトのインスタンスoneに正確に制限する場合に使用されます。これは、データベース、インメモリキャッシュ、またはロボットアームなどの特殊なハードウェアのような共有リソースがある場合に役立ちます。プログラムの多くの部分でこのリソースを使用したい場合があり、リソースへのすべてのアクセスを単一のポイントで実行したい場合があります。シングルトンは常にonlyでこれらの状況を処理する方法ではありませんが、シングルトンmightが良い選択だと私が思う数少ない場所の1つです。

  • 他の回答で引用されている理由から、ギャングオブフォーシングルトンパターンは避けてください。主にそれはテストのために作成する困難に基づいたアンチパターンです。

  • FactoryとDependency Injectionにより、Singletonは廃止されました。最良の答えは、特定のクラスのインスタンスをインスタンス化するか、インスタンス化するかを決定するファクトリを使用することです。このようにして、クラスとそのクライアントは、シングルトンステータスについて責任を負いません。これは、ファクトリによって管理される透過的な問題になります。

  • Springのような依存性注入フレームワークは、追加設定なしでそれを行います(たとえば、特に指定しない限り、Spring Beanはシングルトンです)。

  • 純粋に静的なクラスは、テストとOOの概念の両方を使用する場合に問題があります。私はeverything staticおよびfinalにしたくてたまらない衝動を持つチームを見てきました。そして問題は、なぜCコードを書いていないのですか?

  • 静的クラスに副作用がある場合、それは静的であってはなりません。つまり、共有状態を管理している場合、またはパラメータの状態を変更している場合は、ファクトリが単一の共有インスタンスを渡す通常のクラスである必要があります。共有状態を管理する純粋に静的なクラスは、テストにとって非常に難しい問題になります。

  • 純粋に静的なクラスはその特定のクラスに対するコンパイル時のハードな依存関係も作成します。これにより、コードの拡張機能とテスト機能が実際に損なわれます。数式のような副作用のない、永遠で不変の何かのためにそれを予約したいようです。

したがって、答えは、クラスをシングルトンとして記述せず、その決定をファクトリーに移すことです。また、OO言語では、静的クラスは言語の最も重要な設計側面の一部を欠き、テストが複雑になります。ここでも、特定のセマンティクスを持つワーカークラスを使用して、それらをまとめて生成することができます。あなたの工場によって。

12
Rob

常に1つのインスタンスしか存在せず、アプリケーション全体で使用できるように作成されたシングルトンオブジェクト。

接続プールなどを処理するオブジェクトは、シングルトンの候補として適しています。

  • アプリケーション全体で1つのインスタンスのみが必要です。
  • アプリケーションのさまざまな部分からアクセスできる必要があります
  • 保持しているデータは、他のオブジェクトが現在それをポイントしていない場合でも永続化する必要があります(初期化にコストがかかるオブジェクトを再利用する場合に便利です)。

静的メソッドのみで埋められたクラスは、通常、オブジェクトのように初期化されることを意図したものではありません。静的メソッドのラッパーのようなものです。

私が頻繁に使用するこの例は、パラメーターを取る反復的なタスクを実行するメソッドを持つユーティリティクラスであり、それらを使用して計算を行う/それらをフォーマットする/などです。そして、外部(または少なくとも静的でない)フィールドまたはメソッドを使用せずに結果を返します。ユーティリティクラスを初期化することはありません。静的メソッドをすべての反復的なメソッドに使用します。

これは、私がシングルトンと静的(メソッドで満たされた)クラスを使用する傾向がある方法です。「公式の」標準に準拠しているかどうかはわかりません...

0
Rob