シングルトンパターン は GoF の パターン帳 の完全に支払われたメンバーですが、最近は開発者の世界ではなかなか孤立しているようです。私はまだ ファクトリクラス のために、まだかなりたくさんのシングルトンを使っています、そしてあなたがマルチスレッドの問題に少し注意を払わなければならない間、私はなぜそれらがそんなにひどいのかわかりません。
Stack Overflowは、特にシングルトンが悪であることに誰もが同意すると仮定しているようです。どうして?
「 事実、参考文献、または特定の専門知識 」で回答を裏付けてください。
Brian Buttonからの言い換え:
それらは一般的にグローバルインスタンスとして使用されていますが、なぜそれがそれほど悪いのでしょうか。なぜなら、インターフェースを通してそれらを公開するのではなく、あなたのコードであなたのアプリケーションの依存関係を隠すからです。それを見逃さないようにグローバルなものにすることは コードのにおい です。
彼らは 単一の責任の原則 :に違反しています。というのも、彼らは彼ら自身の創造とライフサイクルをコントロールしているからです。
それらは本質的にコードを厳密に coupled にします。これは、多くの場合、テスト中にそれらを取り出すのをかなり難しくします。
それらはアプリケーションの存続期間中は状態を伝えます。テストを命じる必要があるという状況に陥る可能性があるので、テストには別の打撃が与えられます。これは、単体テストには大きな問題ではありません。どうして?なぜなら、各単体テストは互いに独立しているべきだからです。
シングルトンは一つの(そして唯一の)問題を解決します。
リソースの競合。
いくつかのリソースがあれば
( 1 )は単一のインスタンスしか持てません。
( 2 )あなたはその単一のインスタンスを管理する必要があります、
シングルトン が必要です。
例はあまりありません。ログファイルは大きなものです。あなたはただ一つのログファイルを放棄したくはありません。あなたはそれを適切にフラッシュし、同期し、そして閉じたいです。これは、管理する必要がある単一の共有リソースの例です。
シングルトンが必要になることは稀です。彼らが悪い理由は、彼らが グローバル のように感じ、そして彼らがGoF Design Patterns本の全額支払われたメンバーであるということです。
あなたがあなたがグローバルを必要とすると思うとき、あなたは恐ろしいデザインミスをしているでしょう。
一部のコーディングスノブは、それらを単なる見せかけのグローバルと見なしています。多くの人が goto 文を嫌うのと同じように、 global を使うという考えを嫌う人もいます。私は何人かの開発者が global を避けるために驚くべき長さになっているのを見ました。彼らはそれを失敗の承認として使うことを考えたからです。奇妙だが本当だ。
実際には、 Singleton パターンは単なるプログラミング手法であり、概念のツールキットの中で役に立つ部分です。時々あなたはそれが理想的な解決策であると思うかもしれないのでそれを使う。しかし、 designパターン を使用することを自慢できるように、それを使用することは、 global であるため、これを使用することを拒否するのと同じくらい愚かです。
GoogleのMisko Heveryには、まさにこのトピックに関する興味深い記事がいくつかあります。
シングルトンは病理学的嘘つきです シングルトンが依存関係の連鎖を把握し、アプリケーションを起動またはテストすることを困難にする可能性があることを示すユニットテストの例があります。これはかなり極端な虐待の例ですが、彼がしていることはまだ有効です。
シングルトンはグローバルな状態に過ぎません。グローバル状態はそれをあなたのオブジェクトがそのAPIで宣言されていないものをひそかに手に入れることができるようにし、その結果、シングルトンはあなたのAPIを病理学的嘘つきにします。
すべてのシングルトンがなくなったところ は依存性注入がそれらを必要とするコンストラクタにインスタンスを取得することを容易にしているという点を指摘しています。
私は混乱が人々がシングルトンパターンの本当の応用を知らないという事実によって引き起こされると思います。私はこれを十分に強調することはできません。シングルトンは not グローバルをラップするパターンです。シングルトンパターンは、実行時に 特定のクラスの唯一のインスタンス が存在することを保証するためにのみ使用されるべきです。
彼らはグローバルにそれを使用しているので人々はシングルトンは悪だと思います。シングルトンが見下ろされているのは、この混乱のためです。シングルトンとグローバルを混同しないでください。それが意図されていた目的のために使用されるならば、あなたはシングルトンパターンから極端な利益を得るでしょう。
シングルトンの1つのやや悪い点は、シングルトンを非常に簡単に拡張できないことです。基本的に、何らかの動作 の装飾パターン またはその動作を変更する場合は、そのようなものを組み込む必要があります。また、その1つのことを複数の方法で行いたい場合、コードのレイアウト方法によっては、変更するのがかなり面倒な場合があります。
注意すべきことは、シングルトンを使用する場合、直接アクセスするのではなく、それらを必要とする人に渡すことです...そうでなければ、シングルトンが行うことを複数の方法で行うことを選択した場合、各クラスがシングルトンに直接アクセスする場合、依存関係が埋め込まれるため、変更するのはかなり困難です。
だから基本的に:
public MyConstructor(Singleton singleton) {
this.singleton = singleton;
}
のではなく:
public MyConstructor() {
this.singleton = Singleton.getInstance();
}
この種のパターンは 依存性注入 と呼ばれ、一般に良いことと考えられています。
しかし、他のパターンと同様に...考えてみて、与えられた状況での使用が不適切かどうかを検討してください...規則は通常破られるように作られており、 patterns 考えずに無制限に適用しないでください。
シングルトンパターン自体は問題ではありません。問題は、パターンがオブジェクト指向のツールを使ってソフトウェアを開発している人々がOOの概念をしっかりと把握していなくてもよく使用されることです。この文脈でシングルトンが導入されると、それらは少しの使用のためにヘルパーメソッドを含む管理できないクラスに成長する傾向があります。
シングルトンもテストの観点から問題です。それらは孤立した単体テストを書くのを難しくする傾向があります。制御の反転(IoC)および依存性注入は、ユニットテストに適したオブジェクト指向の方法でこの問題を解決するためのパターンです。
ガベージコレクト 環境では、シングルトンはメモリ管理に関してすぐに問題になる可能性があります。
シングルトンが同期の問題と同様にボトルネックになる可能性があるマルチスレッドのシナリオもあります。
シングルトンは静的メソッドを使って実装されます。静的メソッドは、単調なテストをする人々によって避けられないのです。このサイトのほとんどの人はユニットテストを強く支持しています。それらを避けるための一般的に最も受け入れられている規約は 制御の反転 patternを使うことです。
シングルトンは クラスタリング になるとまた悪いです。それで、あなたはもうあなたのアプリケーションに "厳密に一つのシングルトン"を持っていません。
次のような状況を考えてください。開発者として、データベースにアクセスするWebアプリケーションを作成する必要があります。同時データベース呼び出しが互いに競合しないようにするために、スレッド保存SingletonDao
を作成します。
public class SingletonDao {
// songleton's static variable and getInstance() method etc. omitted
public void writeXYZ(...){
synchronized(...){
// some database writing operations...
}
}
}
つまり、アプリケーションに存在するシングルトンは1つだけであり、すべてのデータベースはこの1つだけを通過し、SingletonDao
だけです。あなたの生産環境は今このようになります:
これまでのところすべて問題ありません。
それでは、Webアプリケーションの複数のインスタンスをクラスタ内に設定したいとします。さて、あなたは突然次のようなものがあります。
それは奇妙に聞こえます、しかし 今あなたはあなたのアプリケーションに多くのシングルトンを持っています 。そしてそれはまさにシングルトンがあるべきではないということです:それの多くのオブジェクトを持つこと。この例に示すように、データベースに対して同期呼び出しを行いたい場合、これは特に悪いです。
もちろん、これはシングルトンの悪い使い方の一例です。しかし、この例のメッセージは次のとおりです。アプリケーションにシングルトンのインスタンスが1つだけ存在することを当てにすることはできません - 特にクラスタ化に関しては。
モノポリーは悪魔であり、非読み取り専用/可変状態のシングルトンは「本当の」問題です...
シングルトンは病理学的嘘つきであるジェイソンの答え で示唆されているように読んだ後、howシングルトンはしばしば誤用されます。
グローバルが悪い理由:
- a。名前空間の競合が発生します
- b。それは不当な方法で状態を公開します
シングルトンに関しては
- a。それらを呼び出す明示的なOO方法は、競合を防ぐため、aをポイントします。問題ではない
- b。 (工場のような)状態のないシングルトンは問題ではありません。状態のあるシングルトンは、再び不変であるか、一度だけ書き込み、多くを読み取る(構成/プロパティファイル)の2つのカテゴリに分類されます。これらは悪くありません。参照ホルダーの一種である可変シングルトンは、あなたが言っているものです。
最後の声明では、彼はブログの「シングルトンは嘘つきだ」という概念に言及しています。
これはどのようにモノポリーに適用されますか?
独占ゲームを開始するには、まず:
現在、実際に独占をしていない人にとって、これらの基準は最高の状態で理想的です。独占の敗北は飲み込むのが困難です。なぜなら、独占は金銭に関するものであり、負けた場合は他のプレイヤーがゲームを終了するのを注意深く観察しなければならず、損失は通常Swiftであり、つぶれます。そのため、通常、ある時点でルールがねじれ、一部のプレーヤーの自己利益を他のプレーヤーを犠牲にして提供します。
友人のボブ、ジョー、エドと独占しているのです。急速に帝国を築き、指数関数的に市場シェアを消費しています。敵は弱体化しており、血の臭いがし始めます(具象的に)。相棒のボブは、すべてのお金をできるだけ多くの低価値資産に集中させましたが、期待したほど高い投資収益率を得ていません。不運の一撃として、ボブはボードウォークに着地し、ゲームから除外されます。
現在、ゲームはフレンドリーなサイコロの転がりから本格的なビジネスに移行しています。ボブは失敗の例にされており、ジョーとエドは「あの男」のようにはなりたくない。だから、あなたが主役であるあなたは、突然、敵になります。ジョーとエドは、テーブルの下での取引、バックインザバックのマネーインジェクション、過小評価されたハウススワッピングなどを練習し始めます。
その後、それらの1つが勝つ代わりに、プロセスが最初から始まります。突然、限られた一連のルールが動いている標的になり、ゲームは、Survivor以降のすべての高評価の現実のテレビ番組の基盤を構成するような社会的相互作用のタイプに退化します。理由は、ルールが変化しており、どのように/なぜ/何を表すべきかについてコンセンサスがないためです。さらに重要なことは、決定を下す人がいないことです。ゲームのすべてのプレイヤーは、その時点で、2人のプレイヤーが疲れすぎてシャレードを維持できず、ゆっくりとあきらめるまで、独自のルールと混乱を続けています。
したがって、ゲームのルールブックがシングルトンを正確に表している場合、独占ルールブックは虐待の一例になります。
これはプログラミングにどのように適用されますか?
可変シングルトンに存在する明らかなスレッドセーフと同期の問題は別として...データのセットが1つある場合、複数の異なるソースによって同時に読み取り/操作でき、アプリケーション実行の存続期間中に存在します。戻って「ここで適切なタイプのデータ構造を使用していますか」と尋ねるのはおそらく良い時間です。
個人的には、プログラマがシングルトンをアプリケーション内のある種のねじれたクロススレッドデータベースストアとして使用することにより、シングルトンを悪用するのを見てきました。コードを直接操作したので、(スレッドセーフにするために必要なすべてのスレッドロックが原因で)低速であり、(同期バグの予測不可能/断続的な性質のために)作業するのが悪夢だったと証明できます。 「生産」条件下でテストすることはほぼ不可能です。確かに、パフォーマンスの問題のいくつかを克服するためにポーリング/シグナリングを使用してシステムを開発できたかもしれませんが、テストの問題を解決できず、「実際の」データベースがはるかに堅牢で同じ機能をすでに達成できるのになぜ悩まされますか/スケーラブルな方法。
シングルトンは、onlyシングルトンが提供するものが必要な場合のオプションです。オブジェクトの書き込み1読み取り専用インスタンス。同じルールは、オブジェクトのプロパティ/メンバーにもカスケードする必要があります。
他の答えとは違って、私はシングルトンの何が悪いのかについて話すのではなく、それらが正しく使われたときにどれほど強力で素晴らしいかをあなたに見せたいのです!
MyModel myModel = Factory.inject(MyModel.class);
MyModel
を継承するTestMyModel
クラスにマップすることができます。MyModel
がインジェクトされるときはいつでもTestMyModel
instreadが得られます。私がタイトルシングルトンで述べたようにシングルインスタンスについてではありません。
それはまた、過度に使われていると感じる人によってはアンチパターンであると考えられ、クラスの唯一のインスタンスが実際には必要とされない状況では不要な制限を導入します。
参考文献(記事からの関連する参考文献のみ)
シングルトンがどのように悪いのかについての私の答えは、常に「彼らは正しくするのは難しい」です。言語の基本的な構成要素の多くはシングルトン(クラス、関数、名前空間、さらには演算子)であり、コンピューティングの他の側面(localhost、デフォルトルート、仮想ファイルシステムなど)の構成要素でもあります。それらは時々トラブルやフラストレーションを引き起こしますが、それらはまた多くのことをより良く機能させることができます。
私が見る2つの最大の失敗は、次のとおりです。それをグローバルなものとして扱い、Singletonクロージャを定義できなかった。
彼らは基本的にそうであるので、誰もがグローバルとしてシングルトンについて話します。しかし、グローバルでの悪い点の多く(残念ながらすべてではありません)は、本質的にグローバルであることからではなく、あなたがそれをどのように使用するかによって生じます。シングルトンにも同じことが言えます。 「単一インスタンス」が「グローバルにアクセス可能」という意味である必要は実際にはないほどです。それはもっと自然な副産物であり、私たちがそれから来ることを私たちが知っているすべての悪いことを考えると、私たちはグローバルなアクセシビリティを悪用するためにそんなに急いでいるべきではありません。プログラマがシングルトンを見ると、常にそのインスタンスメソッドを介して直接アクセスするようです。代わりに、他のオブジェクトと同じようにナビゲートする必要があります。ほとんどのコードは、シングルトンを扱っていることを認識すべきでさえありません(疎結合、そうでしょう?)。それがグローバルであるようにほんの少しのコードだけがオブジェクトにアクセスするならば、多くの害は元に戻されます。インスタンス関数へのアクセスを制限してそれを強制することをお勧めします。
シングルトンの文脈も非常に重要です。シングルトンの定義的な特徴は「ただ一つ」があるということですが、真実はそれがある種のコンテキスト/名前空間の中では「ただ一つ」であるということです。それらは通常、スレッド、プロセス、IPアドレス、またはクラスタごとに1つですが、プロセッサ、マシン、言語の名前空間/クラスローダ/その他、サブネット、インターネットなどに1つずつ存在することもできます。
もう1つ、それほど一般的ではない間違いは、Singletonのライフスタイルを無視することです。 1つだけがあるからといって、シングルトンが「常にあるべきではない」という全能のものであることを意味するわけでもなく、一般に望ましくもありません(開始および終了のないオブジェクトはコード内のあらゆる種類の有用な仮定に違反します最も絶望的な状況の中で。
これらの間違いを避けても、Singletonsは依然としてPITAになる可能性があります。最悪の問題の多くが大幅に軽減されることを確認する準備ができています。 Javaシングルトンを想像してみてください。これは、クラスローダーごとに1回明示的に定義され(スレッドセーフティポリシーが必要です)、定義および作成メソッドと破棄メソッドおよびそれらの「インスタンス」メソッドのライフサイクルを決定するライフサイクルを持ちます。パッケージ保護なので、通常は他の非グローバルオブジェクトを介してアクセスされます。まだ潜在的な問題の原因ですが、確かにはるかに少ない問題です。
残念なことに、シングルトンのやり方の良い例を教えるよりはむしろ。私たちは悪い例を教え、プログラマがしばらくそれらを使わないようにし、そしてそれらが悪いデザインパターンであることを伝えます。
シングルトン自体が悪いというわけではありませんが、GoFのデザインパターンは悪いです。実際に有効である唯一の議論は、GoFデザインパターンがテストに関してそれ自身を貸さないということです、特にテストが並行して実行されるならば。
以下の手段をコードに適用する限り、クラスの単一インスタンスを使用することは有効な構成要素です。
シングルトンとして使用されるクラスがインタフェースを実装していることを確認してください。これにより、スタブやモックを同じインタフェースを使って実装することができます。
シングルトンがスレッドセーフであることを確認してください。それは与えられたことです。
シングルトンは本質的に単純で、過度に複雑ではないはずです。
アプリケーションの実行時に、シングルトンを特定のオブジェクトに渡す必要がある場合は、そのオブジェクトを構築するクラスファクトリを使用し、それを必要とするクラスにシングルトンインスタンスを渡します。
テスト中および確定的な動作を保証するために、実際のクラス自体、またはその動作を実装するスタブ/モックのいずれかとして別のインスタンスとしてシングルトンクラスを作成し、それを必要とするクラスにそのまま渡します。テスト中にシングルトンを必要とするテスト中のオブジェクトを作成するクラスファクタは、その単一のグローバルインスタンスを渡すため、使用しないでください。目的が無効になります。
私たちのソリューションではシングルトンを使用してきましたが、それは並列テストランストリームにおける決定論的な振る舞いを保証するテストが可能です。
私は受け入れられた答えの中の4つの点に対処したいのですが、うまくいけば、誰かが私が間違っている理由を説明することができます。
コード内で依存関係を隠すのはなぜ悪いのでしょうか。隠された依存関係(Cランタイム呼び出し、OS API呼び出し、グローバル関数呼び出し)はすでにたくさんあり、シングルトン依存関係は簡単に見つけることができます(instance()を検索)。
「回避しないようにグローバルなものを作るのはコードの匂いです。」シングルトンをコードの臭いにしないようにするために何かを渡していないのはなぜですか。
シングルトンを回避するためだけに、コールスタック内の10個の関数を介してオブジェクトを渡す場合は、それほど素晴らしいことでしょうか。
単一の責任の原則:これは少しあいまいで、責任の定義によって異なります。関連する質問は、なぜこの 特定の "責任"をクラスに追加するのが重要なのでしょうか。
オブジェクトをクラスに渡すと、そのオブジェクトをクラス内からシングルトンとして使用するよりも密接に結合されるのはなぜですか。
それはなぜ国家が存続する期間を変えるのですか?シングルトンは手動で作成または破棄することができるので、コントロールはまだ存在しており、寿命を非シングルトンオブジェクトの寿命と同じにすることができます。
単体テストについて
Vince Huston にはこれらの基準があり、私には妥当と思われます。
シングルトンは、次の3つの基準がすべて満たされている場合にのみ考慮する必要があります。
- 単一インスタンスの所有権を合理的に割り当てることはできません
- 遅延初期化が望ましい
- グローバルアクセスは、他の方法では提供されていません。
単一インスタンスの所有権、いつ、どのように初期化が行われるのか、およびグローバルアクセスが問題にならないのであれば、Singletonは十分に興味深いものではありません。
パターンが本当に単一のモデルの一部の側面に使用されていると仮定すると、このパターンに本質的な問題はありません。
私は、反動がその過剰利用のせいであると信じています。それは、理解し、実行するのが最も簡単なパターンであるという事実によるものです。
シングルトンは純粋主義者の観点からは悪いです。
実用的な観点から、 シングルトンは開発時間と複雑さのトレードオフです 。
アプリケーションがそれほど変更されないことがわかっている場合は、それらを使用しても問題ありません。要件が予期しない方法で変更された場合は、事態を改善する必要があるかもしれません(ほとんどの場合、これで問題ありません)。
シングルトンは時々 ユニットテスト を複雑にします。
シングルトンはパターンであり、他のツールと同じように使用または悪用される可能性があります。
シングルトンの悪い部分は、一般的にはユーザーです(または、それがするように設計されていないことに対するシングルトンの不適切な使用を言うべきです)。最大の違反者は偽のグローバル変数としてシングルトンを使用しています。
ロガーやデータベース接続など、シングルトンを使用してコードを作成したときに、複数のログまたは複数のデータベースが必要になった場合は、問題があります。
シングルトンは、それらから通常のオブジェクトに移動するのを非常に困難にします。
また、スレッドセーフではないシングルトンを書くのは簡単すぎます。
シングルトンを使用するのではなく、必要なすべてのユーティリティオブジェクトを機能ごとに渡す必要があります。このように、それらすべてをヘルパーオブジェクトにラップすると、単純化することができます。
void some_class::some_function(parameters, service_provider& srv)
{
srv.get<error_logger>().log("Hi there!");
this->another_function(some_other_parameters, srv);
}
Chris Reathによるこのテーマに関する最近の記事は コメントなしのコーディング です。
注:コメントなしのコーディングは無効になりました。ただし、リンク先の記事は別のユーザーによって複製されています。
シングルトンの問題はスコープの拡大、そして カップリング の問題です。単一のインスタンスにアクセスする必要がある状況がいくつかあることを否定するものではありませんが、他の方法で達成することもできます。
私は今、 制御の反転 (IoC)コンテナを中心に設計し、寿命をコンテナで制御できるようにすることを好みます。これにより、単一のインスタンスが存在するという事実に気付かないように、インスタンスに依存するクラスの利点が得られます。シングルトンの寿命は将来変更することができます。私が最近遭遇したそのような例は、シングルスレッドからマルチスレッドへの簡単な調整でした。
あなたがそれを単体テストしようとするときそれがPIAならばそれがあなたがそれをデバッグしようとするときそれはPIAに行くつもりです、バグ修正または強化。
これはまだ誰も言っていないシングルトンに関するもう一つのことです。
ほとんどの場合、「シングルトン性」は、そのインタフェースの特性ではなく、何らかのクラスの実装の詳細です。コントロールコンテナの反転は、この特性をクラスのユーザから隠します。クラスをシングルトンとしてマークする必要があるだけです(たとえば、Javaでは@Singleton
アノテーションを使用)。残りはIoCCが行います。アクセスはすでにIoCCによって管理されているため、シングルトンインスタンスへのグローバルアクセスを提供する必要はありません。したがって、IoCシングルトンに問題はありません。
IoCシングルトンとは反対側のGoFシングルトンは、getInstance()メソッドを介してインタフェース内で "シングルトン性"を公開することになっているため、上記のすべての問題を抱えています。
スレッドセーフではないオブジェクトをシングルトンパターンに入れる人が多すぎます。 DataContextはスレッドセーフではなく、純粋に作業単位オブジェクトであるという事実にもかかわらず、DataContext( LINQ to SQL )がシングルトンパターンで実行される例を見ました。
シングルトンは悪くありません。グローバルにユニークではなく、グローバルにユニークなものを作るときにだけ悪いのです。
ただし、「アプリケーションスコープサービス」(コンポーネントを対話させるメッセージングシステムについて考える)があります。シングルトン用のこのCALLS、「MessageQueue」 - メソッド「SendMessage(...)」を持つクラスです。
その後、いたるところから次のことができます。
MessageQueue.Current.SendMessage(new MailArrivedMessage(...));
そしてもちろん、
MessageQueue.Current.RegisterReceiver(this);
iMessageReceiverを実装するクラス内.
これらは基本的にオブジェクト指向のグローバル変数であるため、通常は必要ないようにクラスを設計できます。
複数の人(またはチーム)が類似または同一の解決策に到達すると、パターンが出現します。多くの人がまだシングルトンをオリジナルの形で、あるいはファクトリテンプレートを使って使っています(AlexandrescuのModern C++ Designでよく議論されています)。オブジェクトの存続期間を管理する際の並行性と困難さが主な障害です。
すべての選択肢と同様に、シングルトンは浮き沈みの公正なシェアを持っています。私はそれらが適度に、特にアプリケーションの寿命を生き残ったオブジェクトのために使用できると思います。彼らが世界的に似ている(そしておそらくそうである)という事実は、おそらく純粋主義者を後押ししている。
シングルトンありません悪、あなたがそれを使うのであれば正しく&最小限。ある時点でシングルトンのニーズに代わる優れたデザインパターンが他にもたくさんあります(&も最高の結果をもたらします)。しかし、一部のプログラマーはそれらの良いパターンに気付いておらず、シングルトンを悪用にするすべての場合にシングルトンを使用します。
第一に、クラスとその共同研究者は、子供たちに焦点を合わせるのではなく、最初に意図した目的を実行する必要があります。ライフサイクル管理(インスタンスが範囲外になったときにインスタンスが作成されたとき)は、クラッドの責任の一部になってはなりません。このために受け入れられているベストプラクティスは、依存性注入を使用して依存性を管理するための新しいコンポーネントを作成または構成することです。
ソフトウェアはより複雑になることが多く、異なる状態を持つ「シングルトン」クラスの複数の独立したインスタンスを持つことは理にかなっています。そのような場合は、シングルトンを取得するためだけにコードをコミットするのは間違っています。 Singleton.getInstance()を使用しても、小規模で単純なシステムでは問題ないかもしれませんが、同じクラスの異なるインスタンスが必要な場合は機能しません。
どのクラスもシングルトンと考えるべきではありませんが、むしろそれはその使用法やそれが依存物を設定するためにどのように使われるかの応用であるべきです。厄介なことにはこれは問題ではありません。ファイルパスは問題にならないと言うだけでなく、DIを使用してより適切な方法でそのような依存関係を管理する必要があります。
シングルトンがテストで引き起こす問題は、ハードコーディングされた単一のユースケース/環境の症状です。テストスイートと多くのテストはそれぞれ個別のもので、シングルトンのハードコーディングと互換性のないものを分離しています。
シングルトン - アンチパターン! Mark Markford著(Overload Journal#57 - 2003年10月)は、Singletonがアンチパターンと見なされている理由についての良い記事です。この記事では、Singletonに代わる2つの代替設計アプローチについても説明しています。
これは私がこれまでのところ答えから欠けていると思うものです:
プロセスアドレス空間ごとにこのオブジェクトの1つのインスタンスが必要な場合(そしてこの要件が変わらないという自信がある限り)、それをシングルトンにする必要があります。
そうでなければ、それはシングルトンではありません。
これは非常に奇妙な要件であり、ユーザーの興味を引くことはほとんどありません。プロセスとアドレス空間の分離は実装の詳細です。 kill
またはタスクマネージャを使用してアプリケーションを停止したい場合にのみ、ユーザーに影響を与えます。
キャッシングシステムを構築する以外に、プロセスごとにインスタンスがあるだけであることが確実である理由はそれほど多くありません。ロギングシステムはどうですか?あなたがより自動的にメッセージの起源をたどることができるように、それはスレッド毎あるいはもっときめの細かい方が良いかもしれません。アプリケーションのメインウィンドウはどうですか?場合によります;何らかの理由ですべてのユーザーの文書を同じプロセスで管理したい場合があります。その場合は、そのプロセスに複数の「メインウィンドウ」があります。
作者からの反論
将来、クラスを単一にしないようにする必要がある場合は、スタックしたままになっています。 まったくそうではありません。 - 単一のデータベース接続シングルトンを使用して接続プールにしたかったのです。すべてのシングルトンは標準的な方法でアクセスされることを忘れないでください。
MyClass.instance
これはファクトリメソッドのシグネチャに似ています。プールから次の接続を返すようにインスタンスメソッドを更新しただけです。他の変更は必要ありません。シングルトンを使用していなければ、それははるかに困難でした。
シングルトンは単なる空想的なグローバルです それについて議論することはできませんが、すべての静的フィールドやメソッドもそうです - インスタンスからではなくクラスからアクセスされるものは基本的にグローバルなのでフィールド?
シングルトンが優れていると言っているのではなく、ここでは「慣習的な知恵」のいくつかを押しのけるだけです。
懸念の分離 をぼかします。
シングルトンがあると仮定すると、クラス内のどこからでもこのインスタンスを呼び出すことができます。あなたのクラスはもはやそれほど純粋ではありません。あなたのクラスは、そのメンバーとそれが明示的に受け取るメンバーに対して動作しなくなります。クラスのユーザーは、クラスが必要とする十分な情報が何であるかわからないので、これは混乱を引き起こします。 encapsulation の全体的な考え方は、ユーザからメソッドの使い方を隠すことですが、メソッド内でシングルトンが使用されている場合は、そのメソッドを正しく使用するためにシングルトンの状態を知る必要があります。これはanti - _ oop _ です。
私の頭の上から: