2089

シングルトン パターンは、GoFパターン ブックの完全な有料メンバーですが、最近、開発者の世界では孤立しているようです。特にfactory classesでは、まだかなり多くのシングルトンを使用しています。マルチスレッドの問題については少し注意する必要がありますが (実際には他のクラスと同様)、なぜそれらがそれほどひどいのかわかりません。

特にスタック オーバーフローは、誰もがシングルトンが悪であることに同意していると想定しているようです。なんで?

「事実、参考文献、または特定の専門知識」で回答を裏付けてください

4

36 に答える 36

1381

ブライアン・バトンからの言い換え:

  1. それらは一般的にグローバルインスタンスとして使用されますが、なぜそれほど悪いのでしょうか? アプリケーションの依存関係をインターフェイスを介して公開するのではなく、コードで非表示にするためです。何かをグローバルに渡さないようにすることは、コードの匂いです。

  2. それらは、単一責任の原則に違反しています。つまり、自分の作成とライフサイクルを制御しているという事実によります。

  3. それらは本質的にコードを密結合させます。これにより、多くの場合、テスト中に偽装することがかなり困難になります。

  4. それらは、アプリケーションの存続期間中、状態を保持します。テストを注文する必要がある状況に陥る可能性があるため、テストへの別のヒットです。これは、単体テストにとって大きな問題です。なんで?各単体テストは互いに独立している必要があるためです。

于 2008-09-26T06:13:44.630 に答える
484

シングルトンは 1 つ (そして 1 つだけ) の問題を解決します。

リソース競合。

あなたがいくつかのリソースを持っている場合

( 1 ) 単一のインスタンスのみを持つことができ、

( 2 ) その単一のインスタンスを管理する必要がある。

シングルトンが必要です。

多くの例はありません。ログファイルは大きなものです。1 つのログ ファイルだけを放棄したくはありません。適切にフラッシュ、同期、および閉じる必要があります。これは、管理する必要がある単一の共有リソースの例です。

シングルトンが必要になることはめったにありません。彼らが悪い理由は、彼らがグローバルであると感じていることと、GoF Design Patterns bookの全額を支払ったメンバーであることです。

グローバルが必要だと思うときは、おそらくひどい設計ミスを犯しています。

于 2008-09-26T23:11:19.387 に答える
376

一部のコーディングスノッブは、彼らを単なる美化されたグローバルとして見下しています。多くの人がgotoステートメントを嫌うのと同じように、 globalを使用するという考えを嫌う人もいます。私は何人かの開発者がグローバルを避けるために途方もない努力をしているのを見てきました。奇妙ですが本当です。

実際には、Singletonパターンは、概念のツールキットの有用な部分である単なるプログラミング手法です。場合によっては、それが理想的なソリューションであることに気付くかもしれませんので、それを使用してください。しかし、デザイン パターンの使用を自慢するためだけにそれを使用することは、それが単にグローバルであるという理由で使用を拒否するのと同じくらい愚かです。

于 2008-09-26T06:13:11.090 に答える
231

Google の Misko Hevery には、まさにこのトピックに関する興味深い記事がいくつかあります...

Singletons are Pathological Liarsには単体テストの例があり、シングルトンによって依存関係チェーンの把握とアプリケーションの起動またはテストがいかに困難になるかを示しています。これは乱用のかなり極端な例ですが、彼の指摘は依然として有効です。

シングルトンはグローバルな状態にすぎません。グローバルな状態により、オブジェクトはAPIで宣言されていないものを密かに取得できるようになり、その結果、シングルトンはAPIを病的な嘘つきにします。

シングルトンはどこへ行ったのかでは、依存性注入によってインスタンスを必要とするコンストラクターへのインスタンスを簡単に取得できるようになったことを指摘しています。

于 2008-09-26T06:08:43.490 に答える
138

この混乱は、人々がシングルトン パターンの実際のアプリケーションを知らないという事実によって引き起こされていると思います。私はこれを十分に強調することはできません。シングルトンは、グローバルをラップするパターンではありません。シングルトン パターンは、実行時に特定のクラスのインスタンスが 1 つだけ存在することを保証するためにのみ使用する必要があります。

シングルトンをグローバルに使用しているため、人々はシングルトンを悪だと考えています。シングルトンが見下されているのは、この混乱のためです。シングルトンとグローバルを混同しないでください。意図した目的で使用すると、Singleton パターンから非常に大きなメリットが得られます。

于 2008-09-26T18:03:07.553 に答える
75

シングルトンの悪い点は、簡単に拡張できないことです。基本的に、動作を変更したい場合は、ある種のデコレータ パターンまたはそのようなものを組み込む必要があります。また、ある日、1 つのことを複数の方法で実行したい場合、コードのレイアウト方法によっては、変更するのがかなり面倒になる場合があります。

注意すべきことの1つは、シングルトンを使用する場合は、直接アクセスするのではなく、必要な人に渡すようにしてください...そうでなければ、シングルトンが行うことを複数の方法で行うことを選択した場合、それはシングルトンに直接アクセスする場合、各クラスが依存関係を埋め込むため、変更するのはかなり困難です。

だから基本的に:

public MyConstructor(Singleton singleton) {
    this.singleton = singleton;
}

それよりも:

public MyConstructor() {
    this.singleton = Singleton.getInstance();
}

この種のパターンは依存性注入と呼ばれ、一般的には良いことだと考えられています。

どんなパターンもそうですが… 考えてみて、与えられた状況での使用が不適切かどうかを考えてみてください… 通常、ルールは破るために作られています。

于 2008-09-26T06:17:12.377 に答える
70

シングルトン パターン自体は問題ではありません。問題は、OO の概念をしっかりと把握していないオブジェクト指向ツールを使用してソフトウェアを開発している人々が、パターンを使用することが多いことです。このコンテキストでシングルトンが導入されると、わずかな使用ごとにヘルパー メソッドを含む管理不能なクラスに成長する傾向があります。

シングルトンは、テストの観点からも問題です。それらは、分離された単体テストの作成を困難にする傾向があります。制御の反転(IoC) と依存性注入は、単体テストに役立つオブジェクト指向の方法でこの問題を克服するためのパターンです。

ガベージ コレクション環境では、メモリ管理に関してシングルトンがすぐに問題になる可能性があります。

シングルトンがボトルネックや同期の問題になる可能性があるマルチスレッドのシナリオもあります。

于 2008-09-26T06:37:29.147 に答える
56

シングルトンは、静的メソッドを使用して実装されます。静的メソッドは、モックやスタブ化できないため、単体テストを行う人によって回避されます。このサイトのほとんどの人は、単体テストの強力な支持者です。それらを回避するための一般的に最も受け入れられている規則は、制御パターンの反転を使用することです。

于 2008-09-26T06:11:11.813 に答える
46

クラスタリングに関しては、シングルトンも悪いです。そのため、アプリケーションには「正確に 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 つだけあるとは限りません。

于 2013-02-22T14:34:10.683 に答える
45
  1. これは、グローバル変数として簡単に (ab) 使用されます。
  2. シングルトンに依存するクラスは、単独での単体テストが比較的困難です。
于 2008-09-26T06:06:42.417 に答える
35

独占は悪魔であり、非読み取り専用/可変状態のシングルトンは「本当の」問題です...

ジェイソンの回答で示唆されているように、Singletons are Pathological Liarsを読んだ後、シングルトンがどのように悪用されることが多いかを示す最も良い例を提供するこの小さな情報に出会いました。

以下の理由で、グローバルは良くありません。

  • a. 名前空間の競合が発生します
  • b. 国家を不当に暴露している

シングルトンに関しては

  • a. それらを呼び出す明示的なオブジェクト指向の方法は、競合を防ぐため、a. 問題ではありません
  • b. 状態のないシングルトンは (工場のように) 問題になりません。状態を持つシングルトンは、再び 2 つのカテゴリに分類できます。1 つは、不変であるか、1 回だけ書き込み、多くを読み取る (構成/プロパティ ファイル) というカテゴリです。これらは悪くありません。参照ホルダーの一種である可変シングルトンは、あなたが話しているものです。

最後の声明で、彼は「シングルトンは嘘つきだ」というブログの概念に言及しています。

これはモノポリーにどのように適用されますか?

独占ゲームを開始するには、まず次のことを行います。

  • 最初にルールを確立し、全員が同じページにいるようにします
  • ゲーム開始時、全員に平等なスタートが与えられる
  • 混乱を避けるために、ルールは 1 セットだけ提示されます。
  • ゲーム中にルールを変更することはできません

さて、モノポリーを実際にプレイしたことがない人にとっては、これらの基準はせいぜい理想的なものです。独占での敗北は飲み込むのが難しいです。なぜなら、独占はお金に関するものだからです。負けた場合は、残りのプレイヤーがゲームを終了するのを丹念に見守る必要があり、通常、負けは迅速で破滅的です。そのため、通常、ルールはある時点でひねられ、他のプレイヤーを犠牲にして一部のプレイヤーの自己利益に奉仕します。

つまり、友人のボブ、ジョー、エドとモノポリーをしているということです。あなたは急速に帝国を築き上げ、指数関数的な速度で市場シェアを消費しています。対戦相手は弱体化し、血のにおいがし始めます (比喩的に)。あなたの相棒のボブは、できるだけ多くの価値の低い物件の行き詰まりに全財産をつぎ込んでいますが、期待したほどの高い投資収益率は得られていません。不運な出来事として、ボブはボードウォークに着陸し、ゲームから除外されました。

今、ゲームは友好的なサイコロを振ることから真剣なビジネスに変わります. ボブは失敗の見本にされており、ジョーとエドは「あの男」のようになりたくない. だから、主役のあなたがいきなり敵になる。ジョーとエドは、テーブルの下での取引、裏での資金注入、過小評価されたハウススワッピングなど、プレーヤーとしてのあなたを弱体化させるあらゆることを、そのうちの1人がトップに立つまで練習し始めます.

その後、どちらかが勝つ代わりに、プロセスが最初からやり直されます。突然、限られた一連のルールが動くターゲットになり、ゲームはサバイバー以来のすべての高評価のリアリティ番組の基礎を構成するタイプの社会的相互作用に退化します. なぜなら、ルールは変化しており、ルールがどのように/なぜ/何を表現するべきかについてコンセンサスが得られていないからです。その時点で、ゲーム内のすべてのプレーヤーが独自のルールを作成しており、2 人のプレーヤーが疲れすぎてシャレードを維持できず、ゆっくりとあきらめるまで混乱が続きます。

したがって、ゲームのルールブックがシングルトンを正確に表している場合、独占ルールブックは乱用の一例になります。

これはプログラミングにどのように適用されますか?

変更可能なシングルトンが提示するすべての明らかなスレッドセーフと同期の問題は別として...複数の異なるソースによって同時に読み取り/操作でき、アプリケーション実行の存続期間中に存在するデータセットが1つある場合、一歩下がって、「ここで正しいタイプのデータ構造を使用しているか」と尋ねるのはおそらく良い時期です。

個人的には、プログラマーがシングルトンをアプリケーション内のねじれたクロススレッド データベース ストアのようなものとして使用することで、シングルトンを悪用しているのを見てきました。コードに直接取り組んだことで、(スレッドセーフにするためにすべてのスレッドロックが必要なため) 遅く、(同期バグの予測不可能/断続的な性質のため) 悪夢のような作業だったことを証明できます。 「生産」条件下でテストすることはほぼ不可能です。確かに、ポーリング/シグナリングを使用していくつかのパフォーマンスの問題を克服するシステムを開発できたかもしれませんが、それではテストの問題は解決されません。 /スケーラブルな方法。

シングルトンは、シングルトンが提供するものが必要な場合にのみ使用できます。オブジェクトの書き込み 1 回読み取り専用インスタンス。同じルールをオブジェクトのプロパティ/メンバーにもカスケードする必要があります。

于 2010-06-25T00:33:49.120 に答える
34

シングルトンは単一のインスタンスではありません!

他の回答とは異なり、シングルトンの何が問題なのかについては話したくありませんが、正しく使用するとどれほど強力で素晴らしいかをお見せしたいと思います!

  • 問題: シングルトンはマルチスレッド環境で問題になる可能性があります
    解決策: シングル スレッドのブートストラップ プロセスを使用して、シングルトンのすべての依存関係を初期化します。
  • 問題: シングルトンをモックするのは難しい。
    解決策: メソッドファクトリパターンを使用してモックを作成する

それを継承MyModelするクラスにマップできます。注入されると、どこでもインストレッドを取得できます。-問題: シングルトンは決して破棄されないため、メモリ リークが発生する可能性があります。解決策:さて、それらを処分してください!アプリにコールバックを実装して、シングルトンを適切に破棄します。シングルトンにリンクされているデータをすべて削除し、最後にファクトリから削除する必要があります。TestMyModelMyModelTestMyModel

タイトルで述べたように、シングルトンは単一インスタンスに関するものではありません。

  • シングルトンは読みやすさを向上させます : クラスを見て、どのシングルトンが注入されたかを確認して、その依存関係を把握できます。
  • シングルトンはメンテナンスを改善します:シングルトンインジェクションを削除したばかりのクラスから依存関係を削除したら、依存関係を移動したばかりの他のクラスの大きなリンクに移動して編集する必要はありません(これは私にとって臭いコードです@Jim Burger )
  • シングルトンはメモリとパフォーマンスを向上させます: アプリケーションで何かが発生し、コールバックのチェーンが長くかかると、メモリとパフォーマンスが浪費されます。不必要なローカル変数の割り当てを避けることによって)。
于 2015-11-08T14:54:16.197 に答える
24

ウィキペディアを参照

また、クラスの唯一のインスタンスが実際には必要ない状況で不必要な制限を導入するために、過度に使用されていると感じている一部の人々によってアンチパターンと見なされています.[1][2][3][4]

参考文献 (記事からの関連参考文献のみ)

  1. ^ アレックス・ミラー. 嫌いなパターン #1: Singleton、2007 年 7 月
  2. ^ スコット・デンズモア. なぜシングルトンが悪なのか、2004 年 5 月
  3. ^ スティーブ・イェジ. 2004 年 9 月、シングルトンは馬鹿げていると見なされる
  4. ^ JB レインズバーガー、IBM. シングルトンを賢く使う , 2001 年 7 月
于 2008-09-26T06:07:32.820 に答える
23

シングルトンがいかに悪いかについての私の答えは、常に「正しく行うのは難しい」です。言語の基本コンポーネントの多くはシングルトン (クラス、関数、名前空間、さらには演算子) であり、コンピューティングの他の側面 (ローカルホスト、デフォルト ルート、仮想ファイルシステムなど) のコンポーネントと同様に、偶然ではありません。それらは時々トラブルや欲求不満を引き起こしますが、多くのことをより良くすることもできます.

私が目にする 2 つの最大の失敗は、それをグローバルのように扱っていることと、Singleton クロージャーを定義していないことです。

シングルトンは基本的にグローバルであるため、誰もがグローバルとして話します。ただし、グローバルの悪い点の多く (すべてではない) は、本質的にグローバルであることに起因するのではなく、それをどのように使用するかに起因します。シングルトンについても同様です。実際には、「単一インスタンス」は「グローバルにアクセス可能」を意味する必要がないため、さらにそうです。それはより自然な副産物であり、私たちが知っているすべての悪いことがそこから来ることを考えると、グローバルアクセシビリティを利用することを急いではいけません. プログラマーが Singleton を見ると、常にそのインスタンス メソッドを介して直接アクセスしているように見えます。代わりに、他のオブジェクトと同じようにナビゲートする必要があります。ほとんどのコードは、Singleton を扱っていることを認識する必要さえありません (疎結合ですよね?)。オブジェクトがグローバルであるかのように、ほんの少しのコードだけがオブジェクトにアクセスすると、多くの害が取り消されます。

Singleton コンテキストも非常に重要です。シングルトンの決定的な特徴は、「1 つだけ」存在することですが、実際には、ある種のコンテキスト/名前空間内で「1 つだけ」です。通常は、スレッド、プロセス、IP アドレス、またはクラスターごとに 1 つですが、プロセッサ、マシン、言語の名前空間/クラス ローダーなど、サブネット、インターネットなどごとに 1 つになることもあります。

もう 1 つの、あまり一般的ではない間違いは、Singleton ライフスタイルを無視することです。シングルトンが1つしかないからといって、シングルトンが「常にそうであり、常にそうなる」という全能性を意味するわけではありません。最も絶望的な状況で。

これらの間違いを回避すれば、シングルトンは依然として PITA である可能性があり、多くの最悪の問題が大幅に軽減されることを確認する準備ができています。クラスローダごとに 1 回と明示的に定義されている Java シングルトンを想像してみてください (つまり、スレッド セーフ ポリシーが必要です)。通常、他の非グローバル オブジェクトを介してアクセスされるようにします。トラブルの潜在的な原因は依然としてありますが、トラブルは確実に少なくなります。

悲しいことに、シングルトンの実行方法の良い例を教えるのではなく. 私たちは悪い例を教え、プログラマーにそれらをしばらく使ってもらい、それから悪い設計パターンであると伝えます。

于 2013-05-29T02:35:49.680 に答える
17

シングルトン自体が悪いわけではありませんが、GoFデザインパターンは悪いです。有効な唯一の実際の議論は、特にテストが並行して実行される場合、GoFデザインパターンはテストに関しては役に立たないということです。

コードで次の手段を適用する限り、クラスの単一インスタンスを使用することは有効な構成です。

  1. シングルトンとして使用されるクラスがインターフェイスを実装していることを確認してください。これにより、同じインターフェイスを使用してスタブまたはモックを実装できます

  2. シングルトンがスレッドセーフであることを確認してください。それは当然のことです。

  3. シングルトンは本質的に単純で、過度に複雑であってはなりません。

  4. シングルトンを特定のオブジェクトに渡す必要があるアプリケーションの実行時に、そのオブジェクトをビルドするクラスファクトリを使用し、クラスファクトリにシングルトンインスタンスをそれを必要とするクラスに渡させます。

  5. テスト中に、決定論的な動作を確認するために、シングルトンクラスを、実際のクラス自体またはその動作を実装するスタブ/モックとして個別のインスタンスとして作成し、それを必要とするクラスにそのまま渡します。テスト中にシングルトンを必要とするテスト対象オブジェクトを作成するクラスファクターは使用しないでください。オブジェクトの単一のグローバルインスタンスに合格するため、目的が損なわれます。

ソリューションでシングルトンを使用し、テスト可能であり、並列テスト実行ストリームで決定論的な動作を保証することで大きな成功を収めました。

于 2012-08-06T01:46:05.137 に答える
17

ヴィンス・ヒューストンには次のような基準がありますが、これは私には妥当と思われます。

シングルトンは、次の 3 つの基準がすべて満たされている場合にのみ考慮する必要があります。

  • 単一インスタンスの所有権を合理的に割り当てることができない
  • 遅延初期化が望ましい
  • それ以外の場合、グローバルアクセスは提供されません

単一インスタンスの所有権、初期化の発生時期と方法、およびグローバル アクセスが問題にならない場合、Singleton は十分に興味深いものではありません。

于 2009-11-23T09:58:11.857 に答える
16

受け入れられた答えの4つのポイントに対処したいと思います。誰かが私が間違っている理由を説明できることを願っています。

  1. コードに依存関係を隠すのはなぜ悪いのですか?すでに数十の非表示の依存関係(Cランタイム呼び出し、OS API呼び出し、グローバル関数呼び出し)があり、シングルトン依存関係は簡単に見つけることができます(instance()を検索してください)。

    「何かをグローバルにして、それを渡さないようにすることは、コードの臭いです。」シングルトンのコードの臭いを避けるために何かを渡さないのはなぜですか?

    シングルトンを回避するためだけに、呼び出しスタック内の10個の関数を介してオブジェクトを渡す場合、それは非常に優れていますか?

  2. 単一責任の原則:これは少し曖昧であり、責任の定義に依存すると思います。関連する質問は、なぜこの特定の「責任」をクラスに追加することが重要なのかということです。

  3. オブジェクトをクラスに渡すと、そのオブジェクトをクラス内からシングルトンとして使用するよりも緊密に結合されるのはなぜですか?

  4. 状態が続く時間を変更するのはなぜですか?シングルトンは手動で作成または破棄できるため、コントロールは引き続き存在し、ライフタイムを非シングルトンオブジェクトのライフタイムと同じにすることができます。

ユニットテストについて:

  • すべてのクラスを単体テストする必要はありません
  • ユニットテストが必要なすべてのクラスがシングルトンの実装を変更する必要があるわけではありません
  • 単体テストが必要で、実装を変更する必要がある場合は、クラスをシングルトンの使用から依存性注入を介してシングルトンに渡すように簡単に変更できます
于 2010-04-07T13:31:48.510 に答える
14

シングルトンは純粋主義の観点からは悪いです。

実用的な観点から、シングルトンは開発時間と複雑さのトレードオフです。

アプリケーションがそれほど変更されないことがわかっている場合は、問題なく使用できます。要件が予期しない方法で変更された場合は、リファクタリングが必要になる可能性があることを知っておいてください(ほとんどの場合、これはかなり問題ありません)。

シングルトンは、ユニットテストを複雑にすることもあります。

于 2011-03-06T18:02:27.880 に答える
13

真に単一のモデルのいくつかの側面に使用されていると仮定すると、パターンに本質的に問題はありません。

反発の原因はその使いすぎであり、それはつまり、これが最も理解しやすく実装しやすいパターンであるという事実によるものだと私は信じています。

于 2008-09-26T06:07:41.870 に答える
13

善悪の議論についてコメントするつもりはありませんが、Springが登場して以来、私はそれらを使用していません。依存性注入を使用することで、シングルトン、サービスロケーター、およびファクトリーに対する私の要件がほとんどなくなりました。少なくとも私が行っている種類の作業 (Java ベースの Web アプリケーション) では、これははるかに生産的でクリーンな環境だと思います。

于 2008-09-26T06:46:29.577 に答える
11

シングルトンはパターンであり、他のツールと同様に使用または悪用できます。

シングルトンの悪い部分は、一般的にユーザーです (または、シングルトンが意図されていないことに不適切に使用されていると言うべきでしょうか)。最大の問題は、シングルトンを偽のグローバル変数として使用することです。

于 2008-09-26T17:24:45.053 に答える
9

ロガーやデータベース接続などのシングルトンを使用してコードを記述した後、複数のログまたは複数のデータベースが必要であることが判明した場合、問題が発生します。

シングルトンは、それらから通常のオブジェクトに移動することを非常に困難にします。

また、非スレッドセーフなシングルトンを書くのはあまりにも簡単です。

シングルトンを使用するのではなく、必要なすべてのユーティリティ オブジェクトを関数から関数に渡す必要があります。次のように、すべてをヘルパー オブジェクトにラップすると、単純化できます。

void some_class::some_function(parameters, service_provider& srv)
{
    srv.get<error_logger>().log("Hi there!");
    this->another_function(some_other_parameters, srv);
}
于 2008-09-26T06:20:10.263 に答える
8

Coding Without Commentsでの Chris Reath によるこの主題に関する最近の記事。

注: コメントなしのコーディングは無効になりました。ただし、リンク先の記事は別のユーザーによって複製されています。

http://geekswithblogs.net/AngelEyes/archive/2013/09/08/singleton-i-love-you-but-youre-bringing-me-down-re-uploaded.aspx

于 2008-10-09T08:18:15.497 に答える
8

シングルトンの問題は、スコープの拡大、つまりカップリングの問題です。単一のインスタンスへのアクセスが必要な状況がいくつかあることは否定できませんが、それは他の方法で実現できます。

私は現在、制御の反転(IoC) コンテナーを中心に設計し、コンテナーによって有効期間を制御できるようにすることを好みます。これにより、インスタンスに依存するクラスが単一のインスタンスがあるという事実を認識しないという利点が得られます。シングルトンの有効期間は将来変更される可能性があります。私が最近遭遇したそのような例は、シングルスレッドからマルチスレッドへの簡単な調整でした。

FWIW、単体テストしようとしたときにPIAの場合、デバッグ、バグ修正、または拡張しようとするとPIAになります。

于 2009-04-28T00:20:32.397 に答える
7

シングルトンは悪くありません。グローバルにユニークではないものをグローバルにユニークにするとき、それはただ悪いことです.

ただし、「アプリケーション スコープ サービス」(コンポーネントを相互作用させるメッセージング システムを考えてください) があります。この呼び出しは、シングルトン、「MessageQueue」、メソッド「SendMessage(...)」を持つクラスを呼び出します。

その後、どこからでも次のことができます。

MessageQueue.Current.SendMessage(新しい MailArrivedMessage(...));

そしてもちろん、次のようにします。

MessageQueue.Current.RegisterReceiver(これ);

IMessageReceiver を実装するクラスで。

于 2010-06-05T10:42:47.853 に答える
7

スレッドセーフではないオブジェクトをシングルトン パターンに入れる人が多すぎます。DataContext はスレッド セーフではなく、純粋に作業単位オブジェクトであるにもかかわらず、シングルトン パターンで実行される DataContext ( LINQ to SQL )の例を見てきました。

于 2008-09-26T06:55:50.490 に答える
6

シングルトンについて、まだ誰も言っていないことがもう 1 つあります。

ほとんどの場合、「単一性」は、インターフェイスの特性ではなく、クラスの実装の詳細です。コントロール コンテナーの反転により、この特性がクラス ユーザーから隠される場合があります。クラスをシングルトンとしてマークする必要があるだけです(@Singletonたとえば、Javaの注釈を使用)。それだけです。残りは IoCC が行います。アクセスは IoCC によって既に管理されているため、シングルトン インスタンスへのグローバル アクセスを提供する必要はありません。したがって、IoC シングルトンに問題はありません。

GoF シングルトンは、IoC シングルトンとは対照的に、getInstance() メソッドを介してインターフェイスで「単一性」を公開することになっているため、上記のすべての影響を受けます。

于 2010-06-01T21:29:40.870 に答える
5

まず、クラスとそのコラボレーターは、依存関係に焦点を当てるのではなく、最初に意図した目的を実行する必要があります。ライフサイクル管理 (インスタンスが作成されたときとスコープ外になったとき) は、クラスの責任の一部であってはなりません。このために受け入れられているベスト プラクティスは、依存関係の挿入を使用して依存関係を管理する新しいコンポーネントを作成または構成することです。

多くの場合、ソフトウェアはより複雑になり、状態の異なる Singleton クラスの複数の独立したインスタンスを持つことが理にかなっています。このような場合、単にシングルトンを取得するためにコードをコミットするのは間違っています。Singleton.getInstance()小規模で単純なシステムでは使用しても問題ないかもしれませんが、同じクラスの別のインスタンスが必要になる可能性がある場合は機能/スケーリングしません。

どのクラスもシングルトンと考えるべきではありませんが、それはその使用法または従属を構成するためにどのように使用されるかのアプリケーションであるべきです。迅速で厄介な場合、これは問題ではありません-ファイルパスは問題ではないと言うルークハードコーディングだけですが、より大きなアプリケーションの場合、そのような依存関係を除外し、DIを使用してより適切な方法で管理する必要があります。

シングルトンがテストで引き起こす問題は、ハードコーディングされた単一の使用ケース/環境の症状です。テスト スイートと多くのテストはそれぞれ個別であり、シングルトンのハード コーディングと互換性のないものを分離しています。

于 2009-04-28T01:14:39.850 に答える
5

適切かつ最小限に使用する場合、シングルトンは悪ではありません。ある時点でシングルトンのニーズを置き換える優れた設計パターンが他にもたくさんあります (また、最良の結果が得られます)。しかし、一部のプログラマーはこれらの良いパターンを認識しておらず、すべてのケースでシングルトンを使用しているため、シングルトンが悪くなっています。

于 2013-11-10T12:11:47.113 に答える
5

これらは基本的にオブジェクト指向のグローバル変数であるため、通常はそれらを必要としないようにクラスを設計できます。

于 2008-09-26T06:05:36.397 に答える
4

複数の人 (またはチーム) が類似または同一のソリューションに到達すると、パターンが現れます。多くの人がまだ元の形式でシングルトンを使用しているか、ファクトリ テンプレートを使用しています (Alexandrescu の Modern C++ Design で適切な議論が行われています)。オブジェクトの有効期間を管理する際の並行性と難しさが主な障害であり、前者はあなたが示唆するように簡単に管理できます。

すべての選択肢と同様に、Singleton には浮き沈みがかなりあります。特にアプリケーションの寿命が尽きるオブジェクトについては、適度に使用できると思います。それらがグローバルに似ている(そしておそらくそうである)という事実は、おそらく純粋主義者を怒らせました。

于 2008-09-26T06:14:25.020 に答える
3

著者からの反論:

将来、クラスを単一ではないものにする必要がある場合は、行き詰まり ます。すべてのシングルトンは標準的な方法でアクセスされることに注意してください。

MyClass.instance

これは、ファクトリ メソッドのシグネチャに似ています。私がしたことは、プールから次の接続を返すようにインスタンス メソッドを更新することだけでした。他の変更は必要ありません。シングルトンを使用していなかったら、それははるかに困難だったでしょう。

シングルトンはただの派手なグローバル です それについて議論することはできませんが、すべての静的フィールドとメソッドもそうです-インスタンスではなくクラスからアクセスされるものはすべて本質的にグローバルであり、静的フィールドの使用についてそれほど多くの反発は見られませんか?

シングルトンが良いと言っているのではなく、ここで「従来の知恵」のいくつかを押し戻しているだけです。

于 2008-10-25T06:12:59.397 に答える
3

シングルトン–アンチパターン! Mark Radford 著 (Overload Journal #57 – 2003 年 10 月) は、Singleton がアンチパターンとみなされる理由についての良い読み物です。この記事では、Singleton を置き換えるための 2 つの代替設計アプローチについても説明します。

于 2008-09-26T06:21:02.883 に答える
3

これは、これまでの回答に欠けていると私が思うものです。

プロセス アドレス空間ごとにこのオブジェクトのインスタンスが 1 つ必要な場合 (そして、この要件が変わらないことを確信している場合)、それをシングルトンにする必要があります。

それ以外の場合は、シングルトンではありません。

これは非常に奇妙な要件であり、ユーザーが関心を持つことはほとんどありません。プロセスとアドレス空間の分離は実装の詳細です。killまたはタスク マネージャーを使用してアプリケーションを停止したい場合にのみ、ユーザーに影響を与えます。

キャッシング システムを構築する以外に、プロセスごとに何かのインスタンスが 1 つだけ存在する必要があると確信できる理由はそれほど多くありません。ログシステムはどうですか?メッセージの発信元をより自動的に追跡できるように、スレッドごとまたはよりきめ細かくする方がよい場合があります。アプリケーションのメイン ウィンドウはどうですか。場合によります; 何らかの理由で、すべてのユーザーのドキュメントを同じプロセスで管理したい場合があります。その場合、そのプロセスには複数の「メイン ウィンドウ」が存在します。

于 2009-07-12T07:47:55.840 に答える
2

それは関心事の分離を曖昧にします。

シングルトンがあるとすると、クラス内のどこからでもこのインスタンスを呼び出すことができます。あなたのクラスは、本来あるべきほど純粋ではなくなりました。クラスは、そのメンバーと明示的に受け取ったメンバーに対して動作しなくなります。クラスのユーザーは、クラスが必要とする十分な情報が何であるかを知らないため、混乱が生じます。カプセル化の全体的な考え方は、メソッドの使用方法をユーザーから隠すことですが、メソッド内でシングルトンが使用される場合、メソッドを正しく使用するにはシングルトンの状態を知る必要があります。これはアンチOOPです。

于 2008-09-26T06:10:34.140 に答える
1

私の頭の上から:

  1. それらは密結合を強制します。シングルトンがそのユーザーとは異なるアセンブリに存在する場合、使用しているアセンブリは、シングルトンを含むアセンブリなしでは機能しません。
  2. たとえば、アセンブリ A はアセンブリ B に依存するシングルトンを持つことができ、アセンブリ B はアセンブリ A のシングルトンを使用できます。コンパイラを壊すことなくすべて。
于 2008-09-26T06:33:47.877 に答える