シングルトンパターンはの完全払込メンバーであるのGoFのパターンの本が、それは最近、むしろ開発者の世界で孤立したようです。私はまだ特に多くのシングルトンを使用しています。特にファクトリークラスでは、マルチスレッドの問題(実際には他のクラスと同様)に少し注意する必要がありますが、なぜそれほどひどいのかはわかりません。
スタックオーバーフローは特に、シングルトンが悪であることに誰もが同意していると想定しているようです。どうして?
「事実、参考文献、または特定の専門知識」で回答をサポートしてください
シングルトンパターンはの完全払込メンバーであるのGoFのパターンの本が、それは最近、むしろ開発者の世界で孤立したようです。私はまだ特に多くのシングルトンを使用しています。特にファクトリークラスでは、マルチスレッドの問題(実際には他のクラスと同様)に少し注意する必要がありますが、なぜそれほどひどいのかはわかりません。
スタックオーバーフローは特に、シングルトンが悪であることに誰もが同意していると想定しているようです。どうして?
「事実、参考文献、または特定の専門知識」で回答をサポートしてください
回答:
ブライアンバトンから言い換え:
それらは一般的にグローバルインスタンスとして使用されますが、なぜそんなに悪いのですか?インターフェースを介してアプリケーションを公開するのではなく、コードでアプリケーションの依存関係を非表示にするためです。何かをグローバルに渡さないようにすることはコードの匂いです。
彼らは単一の責任の原則に違反します。彼らは彼ら自身の創造とライフサイクルを制御するという事実のおかげで。
これらは本質的にコードを密結合します。これにより、多くの場合、テスト中のそれらを偽装することがかなり困難になります。
それらはアプリケーションの存続期間中状態を持ち歩きます。テストを注文する必要がある状況に陥る可能性があるため、テストへのもう1つのヒットは単体テストにとっては大きな問題です。どうして?各ユニットテストは互いに独立している必要があるためです。
シングルトンは1つ(そして1つだけ)の問題を解決します。
リソースの競合。
あなたはそれがあるリソースを持っているなら
(1)は単一のインスタンスのみを持つことができます。
(2)その単一のインスタンスを管理する必要がある
シングルトンが必要です。
多くの例はありません。ログファイルは大きなものです。単一のログファイルを単に破棄する必要はありません。フラッシュし、同期して、適切に閉じたい。これは、管理する必要がある単一の共有リソースの例です。
シングルトンが必要になることはまれです。彼らが悪い理由は、彼らがグローバルのように感じ、GoF Design Patternsの本の完全に支払い済みのメンバーだからです。
グローバルが必要だと思うとき、恐らくひどい設計ミスを犯しています。
一部のコーディングスノッブは、それらを美化されたグローバルとして見下しています。多くの人がgotoステートメントを嫌うのと同じように、グローバルを使用するという考えを嫌う人もいます。何人かの開発者がグローバルを回避するために途方もない時間を費やして、失敗の容認として1つを使用することを検討したのを見ました。奇妙だが真実。
実際には、シングルトンパターンは、概念のツールキットの有用な部分であるプログラミング手法にすぎません。時々、あなたはそれが理想的な解決策であると思うかもしれないので、それを使ってください。しかし、デザインパターンの使用について自慢できるようにそれを使用することは、それが単にグローバルであるため、使用を拒否するのと同じくらい愚かです。
GoogleのMisko Heveryが、まさにこのトピックについていくつかの興味深い記事を持っています...
シングルトンは病理学的である嘘つきは、依存関係の連鎖を理解し、アプリケーションを開始またはテストすることをシングルトンがどのように困難にすることができるかを示すユニットテストの例を持っています。これは虐待のかなり極端な例ですが、彼の主張は今でも有効です。
シングルトンは、グローバルステートにすぎません。グローバル状態はそれを作り、オブジェクトがAPIで宣言されていないものを密かに取得できるようにします。その結果、シングルトンはAPIを病的嘘つきにします。
すべてのシングルトンがどこにあるかというと、依存性注入によってインスタンスを必要とするコンストラクターにインスタンスを簡単に取得できるため、最初の記事で否定されたグローバルなシングルトンの背後にある根本的なニーズが緩和されます。
混乱の原因は、シングルトンパターンの実際の適用を人々が知らないためだと思います。私はこれを十分に強調することはできません。シングルトンは、グローバルをラップするパターンではありません。シングルトンパターンは、実行時に特定のクラスのインスタンスが1つだけ存在することを保証するためにのみ使用する必要があります。
シングルトンはグローバルに使用しているので、シングルトンは悪だと人々は考えています。シングルトンが見下されているのは、この混乱のためです。シングルトンとグローバルを混同しないでください。それが意図された目的で使用された場合、シングルトンパターンから非常に大きなメリットが得られます。
setInstance方法を見たことがあります。)しかし、それはほとんど問題ではありません-シングルトンを「必要とする」というウィニーも、カプセル化に関するおかしなことや何が悪いのかを知りませんでした変更可能なグローバルな状態なので、彼は役に立ちましたか?シングル。フィールド。(そして、そうです、これは起こります。たくさんあります。野生で見たほとんどすべてのシングルトンは、設計により変更可能であり、しばしば
gotoなどでも同じことが言えます。それらは多くの場合機能する可能性がありますが、正直言って、「機能する」だけでは不十分です。従来の知識に逆戻りしたい場合は、アプローチの方法を示すことができます。ある優れた従来のソリューションに比べて。そして、私はシングルトンパターンのそのようなケースを見たことがありません。
getInstanceまたは同様の名前のメソッドを介してそれを公開し、 2番目のインスタンス。率直に言って、その時点では、インスタンスが1つもない場合もあります。
シングルトンの悪い点の1つは、簡単に拡張できないことです。基本的に、動作を変更したい場合は、何らかのデコレータパターンなどを組み込む必要があります。また、ある1つのことを複数の方法で実行したい場合、コードのレイアウト方法によっては、変更がかなり面倒になる場合があります。
注意すべきことの1つは、シングルトンを使用する場合は、直接アクセスするのではなく、必要な人に渡してみることです。そうでない場合、シングルトンが行うことを実行する方法が複数ある場合は、シングルトンに直接アクセスする場合、各クラスが依存関係を埋め込むため、変更はかなり困難です。
だから基本的に:
public MyConstructor(Singleton singleton) {
this.singleton = singleton;
}
のではなく:
public MyConstructor() {
this.singleton = Singleton.getInstance();
}
この種のパターンは依存性注入と呼ばれ、一般的には良いことだと考えられています。
与えられた状況での使用が不適切であるかどうかのいずれかのパターンと同じように...それについて考えてみようと考える...ルールは、通常は破られるために作られ、そしてパターンが考えずにウィリーnilly適用すべきではありません。
getInstance()、(b)はまったく正しくありません。
getInstance()、シングルトンパターンと通常の参照との1つの便利な違いを効果的に放棄できます。残りのコードに関する限り、単一性はもはやプロパティではありません。getInstance()存在するインスタンスの数を知っている、または気にする必要があるのは、これまでの呼び出し元だけです。呼び出し元が1つだけの場合、呼び出し元に参照を格納して再利用させるだけの場合よりも、クラスが単一性を確実に実施するための労力と柔軟性が高くなります。
シングルトンパターン自体は問題ではありません。問題は、オブジェクト指向の概念をしっかりと把握せずに、オブジェクト指向のツールを使用してソフトウェアを開発する人々がこのパターンをよく使用することです。このコンテキストでシングルトンが導入されると、シングルトンは、ほとんど使用しないヘルパーメソッドを含む管理できないクラスに成長する傾向があります。
シングルトンは、テストの観点からも問題です。それらは孤立した単体テストを書くのを難しくする傾向があります。制御の反転(IoC)と依存性注入は、単体テストに役立つオブジェクト指向の方法でこの問題を克服するためのパターンです。
ではガベージコレクト環境シングルトンはすぐにメモリ管理に関する問題になることができます。
シングルトンがボトルネックになる可能性があるマルチスレッドシナリオと同期の問題もあります。
シングルトンは静的メソッドを使用して実装されます。静的メソッドはモックやスタブができないため、単体テストを行う人は避けます。このサイトのほとんどの人々は、ユニットテストの大きな支持者です。それらを回避するために最も一般的に受け入れられている規則は、制御パターンの反転を使用することです。
Singleton。ただし、これはテストプロセスを非常に複雑にします。1つには、今度はクラスを自由にアンロードできるようにする必要があります(ほとんどの言語では実際にはオプションではありません)。または、各テストで新しいVMを開始できる必要があります(読み取り:テストには何千倍も時間がかかる場合があります)。ただし、2つについては、依存関係Singletonは実装の詳細であり、テスト全体に漏れています。
クラスタリングに関しても、シングルトンは良くありません。そのため、アプリケーションに「厳密に1つのシングルトン」はもうありません。
次の状況を考慮してください。開発者は、データベースにアクセスするWebアプリケーションを作成する必要があります。同時データベース呼び出しが互いに競合しないようにするには、thread-saveを作成します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つしかないことは信頼できません。特に、クラスタリングに関してはそうです。
独占は悪魔であり、非読み取り専用/可変状態のシングルトンは「本当の」問題です...
読んだ後シングルトンは、病理学嘘つきですで提案されているようにジェイソンの答え私は最良の提示例提供し、この小さなちらほら出くわしたかシングルトンがしばしば誤用されているが。
グローバルは悪いです:
- a。名前空間の競合が発生します
- b。不当な方法で状態を公開します
シングルトンになると
- a。それらを呼び出す明示的なオブジェクト指向の方法は、競合を防ぐため、aをポイントします。問題ではありません
- b。状態のないシングルトンは(工場のように)問題ありません。状態を持つシングルトンは、再び2つのカテゴリに分類される可能性があります。それらは不変であるか、1回だけ書き込み、多くのファイルを読みます(config / propertyファイル)。これらは悪くないです。リファレンスホルダーの一種であるミュータブルシングルトンは、あなたが話しているものです。
最後の声明で彼はブログの「シングルトンは嘘つきだ」という概念について言及している。
これはモノポリーにどのように当てはまりますか?
独占のゲームを始めるには、まず:
さて、本当に独占をやったことがない人にとって、これらの基準は最高の状態で理想的です。独占の敗北は飲み込むのが難しいです。なぜなら、独占はお金の問題であり、もし負けた場合、他のプレイヤーがゲームを終えるのをじっくりと見なければならず、通常、損失は迅速でつぶれます。したがって、ルールは通常、他の人を犠牲にして一部のプレーヤーの自己利益を果たすために、ある時点でねじれます。
あなたは友達のボブ、ジョー、エドと独占をしています。あなたは帝国を急速に構築し、市場シェアを指数関数的に消費しています。対戦相手が弱くなり、血のにおいがし始めます(比喩的に)。あなたの相棒ボブは、彼のお金のすべてを可能な限り多くの低価値の物件にグリッドロックするために投入しましたが、彼は彼が期待したように高い投資収益率を受け取っていません。ボブは不運のストロークとしてボードウォークに着地し、ゲームから興奮します。
今やゲームはフレンドリーなサイコロの転がりから本格的なビジネスへと進んでいきます。ボブは失敗の例にされており、ジョーとエドは「あの男」のようになってしまいたくありません。それで、あなたが主役になることで、突然、あなたは敵になります。ジョーとエドは、テーブルの下での取引、バックザバックマネーインジェクション、過小評価されたハウススワッピング、そして一般的に、いずれかがトップに上がるまでプレイヤーとしての弱点となる練習を始めます。
次に、そのうちの1人が勝つ代わりに、プロセスが最初から始まります。突然、有限のルールのセットが動くターゲットになり、ゲームは、Survivor以降のすべての高評価の現実のテレビ番組の基礎を構成するタイプの社会的相互作用に退化します。なぜ、ルールが変化し、ルールがどのように/なぜ/何を表すのかについてコンセンサスがないためであり、さらに重要なのは、決定を下す人がいないためです。その時点で、ゲーム内のすべてのプレーヤーは自分のルールを作成し、2人のプレーヤーが疲れすぎてシャレードを維持し、ゆっくりと諦めるまで、混乱が続きます。
したがって、ゲームのルールブックがシングルトンを正確に表す場合、独占ルールブックは乱用の一例になります。
これはプログラミングにどのように適用されますか?
変更可能なシングルトンが存在する明らかなすべてのスレッド安全性と同期の問題は別として、1つのデータセットがある場合、複数の異なるソースによって同時に読み取り/操作でき、アプリケーション実行の存続期間中に存在します。たぶん、「ここで正しいタイプのデータ構造を使用していますか」と尋ねて、今がよい時でしょう。
個人的には、プログラマーがシングルトンをアプリケーション内のある種のねじれたクロススレッドデータベースストアとして使用することによってシングルトンを悪用するのを見てきました。コードに直接取り組んだので、それが遅く(スレッドセーフにするために必要なすべてのスレッドロックのため)、取り組むのが悪夢だった(同期バグの予測できない/断続的な性質のため)ことを証明できます。 「実稼働」条件下でテストすることはほとんど不可能です。確かに、システムはポーリング/シグナリングを使用してパフォーマンスの問題のいくつかを克服するように開発できたかもしれませんが、テストの問題を解決できず、「実際の」データベースがはるかに堅牢で同じ機能をすでに実現できるのに困る理由/スケーラブルな方法。
シングルトンは、シングルトンが提供するものを必要とする場合のみのオプションです。オブジェクトの書き込み専用の読み取り専用インスタンス。同じルールは、オブジェクトのプロパティ/メンバーにもカスケードする必要があります。
Singleton.getInstance()。リフレクションをサポートする言語は、One True Instanceが格納されるフィールドを設定することで、その問題を回避できる場合があります。ただし、IMOは、別のクラスのプライベートな状態をざっと見回すと、テストの信頼性が少し低下します。
他の回答とは異なり、私はシングルトンの何が問題になっているのかを話したくありませんが、適切に使用したときのパワフルで素晴らしいものを紹介します!
あなたはそれを継承MyModelするTestMyModelクラスにマップすることができます、どこにMyModel注入されるとあなたはTestMyModel混乱するでしょう。- 問題:シングルトンは破棄されないため、メモリリークを引き起こす可能性があります。
解決策:さて、それらを処分してください!アプリにコールバックを実装して、シングルトンを適切に破棄します。シングルトンにリンクされているデータをすべて削除し、最後にファクトリから削除します。
タイトルで述べたように、シングルトンは単一のインスタンスではありません。
Settingsでは、どのウィジェットからでもアクセスできるシングルトンオブジェクトを使用しているため、各ウィジェットは表示される数値のフォーマット方法を認識しています。それがグローバルにアクセス可能なオブジェクトでない場合、コンストラクター内のすべてのウィジェットにコンストラクターに挿入し、その参照をメンバー変数として保持する必要があります。これはメモリと時間のひどい無駄です。
シングルトンがいかに悪いかについての私の答えは常に「彼らは正しく行うのが難しい」です。言語の基本コンポーネントの多くはシングルトン(クラス、関数、名前空間、さらには演算子)であり、コンピューティングの他の側面(localhost、デフォルトルート、仮想ファイルシステムなど)のコンポーネントも同様であり、偶然ではありません。それらは時々トラブルやフラストレーションを引き起こしますが、多くのものがLOTをより良く機能させることにもなります。
私が目にする2つの最大の失敗は、グローバルのように扱うことと、シングルトンクロージャを定義できないことです。
シングルトンは基本的にグローバルなので、誰もがシングルトンをグローバルとして話します。ただし、グローバルの悪さの多く(悲しいことに、すべてではありません)は、本質的にグローバルであることからではなく、それをどのように使用するかに起因します。同じことがシングルトンにも当てはまります。実際には、「単一インスタンス」が「グローバルにアクセス可能」を意味する必要はないため、さらに多くなります。これはより自然な副産物であり、それが原因であることがわかっているすべての悪い点を考えると、グローバルアクセシビリティを利用するためにそんなに急いではいけません。プログラマは、シングルトンを見ると、常にインスタンスメソッドを介して直接アクセスしているように見えます。代わりに、他のオブジェクトと同じようにナビゲートする必要があります。ほとんどのコードは、それがシングルトン(疎結合、そうですか?)を扱っていることに気づいてさえいるべきではありません。ほんの少しのコードがグローバルであるかのようにオブジェクトにアクセスする場合、多くの害が取り消されます。
シングルトンのコンテキストも非常に重要です。シングルトンの明確な特徴は「1つだけ」があることですが、真実はある種のコンテキスト/名前空間内では「1つだけ」です。それらは通常、スレッド、プロセス、IPアドレス、またはクラスターごとに1つですが、プロセッサー、マシン、言語名前空間/クラスローダー/何でも、サブネット、インターネットなどの1つにすることもできます。
あまり一般的ではないもう1つの間違いは、シングルトンのライフスタイルを無視することです。シングルトンが1つしかないからといって、シングルトンが「常にそうであり、常にそうである」という全能であるとは限りません。また、一般的に望ましいことでもありません最も絶望的な状況で。
これらのミスを回避しても、シングルトンはPITAのままです。最悪の問題の多くが大幅に軽減されていることを確認する準備ができています。クラスローダーごとに1回(スレッドセーフポリシーが必要であることを意味する)として明示的に定義され、定義された作成メソッドと破棄メソッド、およびそれらが呼び出されるタイミングと方法を指示するライフサイクル、およびその「インスタンス」メソッドが持つJavaシングルトンを想像してください。パッケージ保護のため、通常は他の非グローバルオブジェクトを介してアクセスされます。まだトラブルの潜在的な原因ですが、間違いなくはるかに少ないトラブルです。
悲しいことに、シングルトンのやり方の良い例を教えるのではなく。私たちは悪い例を教え、プログラマーがそれらをしばらく使い切ってから、それらが悪い設計パターンであることを伝えます。
また、過度に使用されていると感じる一部の人々によってアンチパターンと見なされ、クラスの唯一のインスタンスが実際には必要とされない状況で不要な制限が導入されます。[1] [2] [3] [4]
参照(記事からの関連参照のみ)
シングルトン自体が悪いというわけではありませんが、GoFデザインパターンは悪いです。本当に有効な唯一の議論は、特にテストが並行して実行される場合、GoFデザインパターンがテストに関して役に立たないことです。
コードで次の手段を適用する限り、クラスの単一のインスタンスを使用することは有効な構成です。
シングルトンとして使用されるクラスがインターフェースを実装していることを確認してください。これにより、同じインターフェイスを使用してスタブまたはモックを実装できます
シングルトンがスレッドセーフであることを確認してください。それは当然です。
シングルトンは、本質的に単純で、過度に複雑であってはなりません。
アプリケーションの実行時に、シングルトンを特定のオブジェクトに渡す必要がある場合は、そのオブジェクトを構築するクラスファクトリを使用し、クラスファクトリにシングルトンインスタンスを必要なクラスに渡させます。
テスト中および確定的な動作を保証するために、実際のクラス自体またはその動作を実装するスタブ/モックとして、個別のインスタンスとしてシングルトンクラスを作成し、それを必要なクラスにそのまま渡します。テスト中にシングルトンを必要とするテスト対象のオブジェクトを作成するクラスファクターを使用しないでください。オブジェクトの単一のグローバルインスタンスを渡すため、目的に反することになります。
私たちのソリューションではシングルトンを使用しており、テスト可能であり、テストの並列実行ストリームでの確定的な動作を保証する大きな成功を収めています。
受け入れられた回答の4つのポイントに対処したいと思います。うまくいけば、誰かが私が間違っている理由を説明できれば幸いです。
コードの依存関係を隠すのはなぜ悪いのですか?すでに数十の隠れた依存関係(Cランタイム呼び出し、OS API呼び出し、グローバル関数呼び出し)があり、シングルトン依存関係は簡単に見つけることができます(instance()を検索)。
「何かをグローバルに渡さないようにすることは、コードの匂いです。」シングルトンをコードのにおいにしないようにするために、何も渡さないのはなぜですか?
シングルトンを回避するためだけに、コールスタックで10個の関数を介してオブジェクトを渡す場合、それは素晴らしいことですか?
単一の責任の原則:これは少しあいまいで、責任の定義に依存すると思います。関連する質問は、なぜこの特定の「責任」をクラスの問題に追加するのでしょうか。
オブジェクトをクラスに渡すと、そのオブジェクトをクラス内からシングルトンとして使用するよりも強く結合されるのはなぜですか?
なぜ状態が続く期間が変わるのですか?シングルトンは手動で作成または破棄できるため、コントロールはそのまま残り、ライフタイムを非シングルトンオブジェクトのライフタイムと同じにすることができます。
単体テストについて:
ビンスヒューストンには次のような基準があります。
シングルトンは、次の3つの基準がすべて満たされた場合にのみ検討する必要があります。
- 単一インスタンスの所有権を合理的に割り当てることはできません
- 遅延初期化が望ましい
- 他の方法ではグローバルアクセスは提供されません
単一インスタンスの所有権、初期化がいつどのように行われるか、およびグローバルアクセスが問題にならない場合、シングルトンは十分に興味深いものではありません。
シングルトンは純粋主義者の観点からすると悪いです。
実用的な観点から見ると、シングルトンは開発時間と複雑さのトレードオフです。
アプリケーションがそれほど変更されないことがわかっている場合は、問題なく使用できます。要件が予期しない方法で変更された場合は、リファクタリングが必要になる場合があることを知っておいてください(ほとんどの場合、問題はありません)。
真に単一であるモデルの一部の側面に使用されていると想定して、パターンには本質的に問題はありません。
私は、反動がその過剰使用によるものであると私は考えています。これは、理解し、実装するのが最も簡単なパターンであるという事実によるものです。
私は善悪の論点についてコメントするつもりはありませんが、春が来て以来、それらを使用していません。依存性注入を使用すると、シングルトン、サービスロケーター、およびファクトリーに対する私の要件がほとんど取り除かれました。これは、少なくとも私が行うタイプの作業(JavaベースのWebアプリケーション)の場合、はるかに生産的でクリーンな環境だと思います。
シングルトンはパターンであり、他のツールと同じように使用または乱用できます。
シングルトンの悪い部分は、一般的にユーザーです(または、シングルトンが意図されていないことにシングルトンを不適切に使用していると言うべきでしょう)。最大の違反者は、シングルトンを偽のグローバル変数として使用しています。
ロガーやデータベース接続などのシングルトンを使用してコードを記述し、その後、複数のログまたは複数のデータベースが必要であることに気付いた場合、問題が発生します。
シングルトンは、それらから通常のオブジェクトに移動することを非常に困難にします。
また、スレッドセーフでないシングルトンを作成するのは簡単すぎます。
シングルトンを使用するのではなく、必要なすべてのユーティリティオブジェクトを関数間で渡す必要があります。次のように、それらすべてをヘルパーオブジェクトにラップすると、単純化できます。
void some_class::some_function(parameters, service_provider& srv)
{
srv.get<error_logger>().log("Hi there!");
this->another_function(some_other_parameters, srv);
}
シングルトンの問題は、スコープの拡大、したがって結合の問題です。単一のインスタンスへのアクセスが必要な状況がいくつかあり、他の方法で実現できることは否定できません。
私は現在、制御の反転(IoC)コンテナーを中心に設計し、存続期間をコンテナーによって制御できるようにしています。これにより、インスタンスに依存しているクラスが、インスタンスが1つしかないことを意識する必要がなくなります。シングルトンの寿命は将来変更される可能性があります。そのような例として、最近遭遇したのは、シングルスレッドからマルチスレッドへの簡単な調整でした。
FWIW、それを単体テストしようとしたときにPIAである場合、デバッグ、バグ修正、または拡張しようとしたときにPIAになります。
コメントなしのコーディングでのクリス・リースによるこの主題に関する最近の記事。
注:コメントなしのコーディングは無効になりました。ただし、リンクされている記事は別のユーザーによって複製されました。
シングルトンは悪くありません。グローバルにユニークではない何かをグローバルにユニークにするのは悪いことです。
ただし、「アプリケーションスコープサービス」(コンポーネントを相互作用させるメッセージングシステムについて考えてください)があります。これは、シングルトンを呼び出す「MessageQueue」-メソッド「SendMessage(...)」を持つクラスです。
その後、どこからでも以下を実行できます。
MessageQueue.Current.SendMessage(new MailArrivedMessage(...));
そしてもちろん、次のようにします。
MessageQueue.Current.RegisterReceiver(this);
IMessageReceiverを実装するクラス内。
スレッドセーフではないオブジェクトをシングルトンパターンに配置する人が多すぎます。DataContextはスレッドセーフではなく、純粋に作業単位オブジェクトであるにもかかわらず、シングルトンパターンで実行される DataContext(LINQ to SQL)の例を見てきました。
シングルトンについて、まだ誰も言っていないことがもう1つあります。
ほとんどの場合、「単一性」は、そのインターフェースの特性ではなく、あるクラスの実装の詳細です。コントロールコンテナを反転すると、この特性がクラスユーザーから見えなくなる場合があります。クラスをシングルトン(@Singletonたとえば、Javaのアノテーションを使用)としてマークする必要があるだけです。残りはIoCCが行います。アクセスは既にIoCCによって管理されているため、シングルトンインスタンスへのグローバルアクセスを提供する必要はありません。したがって、IoCシングルトンに問題はありません。
IoCシングルトンの反対のGoFシングルトンは、getInstance()メソッドを介してインターフェースに「単一性」を公開することになっているため、上記のすべてに影響を受けます。
シングルトンはありません、あなたがそれを使用する場合、悪適切に&最小限に。ある時点でシングルトンの必要性に取って代わる、他にも多くの優れた設計パターンがあります(そして最良の結果も得られます)。しかし、一部のプログラマーはこれらの良いパターンを認識せず、すべてのケースでシングルトンを使用しているため、シングルトンは悪人になっています。
まず、クラスとその共同作業者は、扶養家族に焦点を当てるのではなく、最初に意図した目的を実行する必要があります。ライフサイクル管理(インスタンスが作成されたとき、およびスコープから外れたとき)は、クラスの責任の一部であってはなりません。このために受け入れられているベストプラクティスは、依存関係注入を使用して依存関係を管理する新しいコンポーネントを作成または構成することです。
多くの場合、ソフトウェアはより複雑になり、状態の異なるシングルトンクラスの複数の独立したインスタンスを持つことは理にかなっています。そのような場合、シングルトンを単に取得するためのコードをコミットすることは間違っています。Singleton.getInstance()小さな単純なシステムでは使用しても問題ないかもしれませんが、同じクラスの別のインスタンスが必要な場合は機能しません。
クラスをシングルトンと見なすべきではありませんが、それは、その使用法または依存関係を構成するためにどのように使用されるかを適用したものでなければなりません。迅速で厄介な問題の場合、これは問題ではありません。ハードコーディングを行うだけでファイルパスは問題にならないと言うだけですが、大きなアプリケーションでは、このような依存関係を除外して、DIを使用してより適切な方法で管理する必要があります。
テストでシングルトンが引き起こす問題は、ハードコードされた単一の使用例/環境の症状です。テストスイートと多くのテストはそれぞれ個別のものであり、シングルトンのハードコーディングと互換性のないものを分離しています。
それらは基本的にオブジェクト指向のグローバル変数であるため、通常、それらを必要としないようにクラスを設計できます。