68

シングルトンは熱く議論されているデザイン パターンであるため、スタック オーバーフロー コミュニティがシングルトンについてどう考えているかに興味があります。

「シングルトンは怠惰なプログラマー向けだ!」だけでなく、意見の理由を教えてください。

シングルトンの使用に反対していますが、この問題に関するかなり良い記事があります: Scientificninja.com: performant-singletons

他に良い記事を持っている人はいますか?多分シングルトンをサポートしていますか?

4

23 に答える 23

56

シングルトンを守るために:

  • グローバルには標準で強制される初期化順序がないため、グローバルほど悪くはありません。また、素朴なまたは予期しない依存順序による非決定論的なバグを簡単に確認できます。シングルトン (ヒープに割り当てられていると仮定) は、すべてのグローバルの後、コード内の非常に予測可能な場所に作成されます。
  • これらは、低速の I/O デバイスへのインターフェイスなど、リソースを遅延させる/キャッシュするシステムに非常に役立ちます。遅いデバイスへのシングルトン インターフェイスをインテリジェントに構築し、誰もそれを呼び出さなければ、時間を無駄にすることはありません。別のコードが複数の場所からそれを呼び出す場合、シングルトンは両方のキャッシュを同時に最適化し、二重ルックアップを回避できます。また、シングルトン制御のリソースでのデッドロック状態を簡単に回避できます。

シングルトンに対して:

  • C++ では、シングルトンの後に自動クリーンアップする良い方法はありません。 回避策と少しハックな方法がありますが、シングルトンのデストラクタが常に呼び出されるようにする単純で普遍的な方法はありません。これは、メモリに関してはそれほどひどいものではありません。この目的のために、これをグローバル変数と考えてください。ただし、シングルトンが他のリソースを割り当て (たとえば、いくつかのファイルをロックする)、それらを解放しないと、問題が発生する可能性があります。

私自身の意見:

私はシングルトンを使用していますが、合理的な代替手段がある場合は使用しないでください。これまでのところ、これはうまく機能しており、テストする作業が少し増えますが、テスト可能であることがわかりました。

于 2008-09-15T17:38:23.497 に答える
38

Google には、Java 用のSingleton Detectorがあります。これは、Google で作成されたすべてのコードで実行する必要があるツールとして始まったと思います。シングルトンを削除する簡単な理由:

テストが困難になり、設計の問題が隠される可能性があるためです。

より明確な説明については、Google の「 Why Singletons Are Controversial 」を参照してください。

于 2008-08-15T02:40:44.337 に答える
31

シングルトンは、仮装したグローバル変数の集まりです。

グローバル変数には、シングルトンと同様に用途がありますが、厄介なグローバル変数を使用する代わりに、シングルトンでクールで便利なことをしていると思うなら (グローバル変数が悪いことは誰もが知っています)、残念ながら誤解されています。

于 2008-08-15T02:12:11.260 に答える
26

シングルトンの目的は、クラスがインスタンスを 1 つだけ持つようにし、そのインスタンスへのグローバルなアクセス ポイントを提供することです。ほとんどの場合、焦点は単一のインスタンス ポイントにあります。それがGlobaltonと呼ばれたとしたら想像してみてください。これは、(通常は) グローバル変数の否定的な意味合いを強調するため、あまり魅力的ではないように思えます。

シングルトンに対する良い議論のほとんどは、シングルトンのテストダブルを作成するのは簡単ではないため、テストで提示される困難に関係しています。

于 2008-08-15T00:48:40.523 に答える
23

Google Testing ブログには、Miško Heveryによるシングルトンに関する 3 つの非常に優れたブログ投稿があります。

  1. シングルトンは病的な嘘つき
  2. すべてのシングルトンはどこへ行った?
  3. シングルトンの根本原因
于 2008-09-15T17:52:06.537 に答える
20

シングルトンは、よく誤用されていますが、恐ろしいパターンではありません。この誤用は、それがより簡単なパターンの 1 つであり、シングルトンに慣れていないほとんどの人がグローバルな副作用に惹かれているためだと思います。

Erich Gammaは、シングルトンは GOF ブックに含まれないことを望んでいるパターンであり、設計が悪いと述べていました。私は反対する傾向があります。

任意の時点でオブジェクトの単一インスタンスを作成するためにパターンが使用されている場合、そのパターンは正しく使用されています。グローバルな効果を与えるためにシングルトンが使用されている場合、それは正しく使用されていません。

短所:

  • シングルトンを呼び出すコード全体で1つのクラスに結合しています
    • インスタンスをモック オブジェクトに置き換えるのが難しいため、単体テストに手間がかかる
    • 複数のインスタンスが必要なために後でコードをリファクタリングする必要がある場合は、シングルトン クラスがそれを使用するオブジェクトに (インターフェイスを使用して) 渡された場合よりも面倒です。

利点:

  • クラスの 1 つのインスタンスは、任意の時点で表されます。
    • 設計上、これを強制しています
  • インスタンスは必要なときに作成されます
  • グローバルアクセスは副作用です
于 2009-02-19T22:33:43.710 に答える
17

私はめったにシングルトンを使用しないため、ひよこは私を掘り下げます。いいえ、真剣に、私はシングルトン パターンが大好きです。あなたが理由を知っている?なぜなら:

  1. 私は怠け者。
  2. 何も問題はありません。

確かに、「専門家」は「単体テスト」と「依存性注入」についてたくさんの話を投げかけますが、それはすべてディンゴの腎臓の負荷です. シングルトンは単体テストが難しいと思いますか? 問題ない!すべてを公開宣言するだけで、クラスをグローバルな良さの楽しい家に変えることができます。1990 年代のハイランダーという番組を覚えていますか? シングルトンは、次のような理由でそのようなものです。 A. 死ぬことはありません。および B. 存在できるのは 1 つだけです。したがって、これらすべての DI ウィニーに耳を傾けるのをやめ、放棄してシングルトンを実装してください。ここにいくつかの正当な理由があります...

  • 誰もがそれをやっています。
  • シングルトンパターンはあなたを無敵にします。
  • シングルトンは「勝つ」(アクセントによっては「楽しい」)と韻を踏む。
于 2009-09-09T17:14:22.987 に答える
8

シングルトンパターンの使用については大きな誤解があると思います。ここでのコメントのほとんどは、グローバルデータにアクセスする場所としてそれを参照しています。ここで注意する必要があります-パターンとしてのシングルトンはグローバルにアクセスするためのものではありません。

シングルトンは、指定されたクラスのインスタンスを1つだけ持つために使用する必要があります。パターンリポジトリには、シングルトンに関する優れた情報があります。

于 2008-08-27T01:20:26.250 に答える
6

私が一緒に働いた同僚の 1 人は、非常にシングルトン志向でした。マネージャーや上司のようなオブジェクトがあるときはいつでも、彼はそれをシングルトンにしました。そして、システムがいくつかの新しい要件を取り上げるたびに、複数のインスタンスを許可する完全に正当な理由があることが判明しました。

ドメインモデルが(「提案」ではなく)シングルトンがあることを指示する場合は、シングルトンを使用する必要があると思います。他のすべてのケースは、偶然にもクラスの単一インスタンスです。

于 2008-09-22T11:48:58.713 に答える
5

聖戦!わかりました。見てみましょう。前回デザインをチェックしたとき、警察が言った。

シングルトンは自動テストを妨げるため、問題があります。テストケースごとにインスタンスを新たに作成することはできません。代わりに、ロジックは、簡単にインスタンス化してテストできるクラス(A)に含める必要があります。別のクラス(B)は、作成の制約を担当する必要があります。単一責任の原則を前面に!AにアクセスするためにBを経由することになっていることをチームが知っている必要があります-一種のチームコンベンションです。

私はほとんど同意します。

于 2008-08-23T17:22:32.087 に答える
5

ここでかわいそうなシンゲルトンを救う方法を考えてみましたが、難しいことは認めざるを得ません。それらの正当な使用法はほとんど見たことがなく、依存性注入と単体テストを実行する現在のドライブでは、それらを使用するのは非常に困難です。それらは間違いなく、デザインパターンを使ったプログラミングの「カーゴカルト」の現れです。私は、「GoF」の本を読んだことはないが、「シンゲルトン」を知っているため、「パターン」を知っている多くのプログラマーと仕事をしてきました。

私はオリオンに反対しなければなりませんが、ほとんどの場合、ドレスのグローバル変数ではなく、ドレスのグローバルサービス(メソッド)のように、シンゲルトンが乱用されているのを見てきました。CLR インターフェイスを介してセーフ モードで SQL Server 2005 で Singeltons を使用しようとすると、システムがコードにフラグを立てることに注意してください。問題は、実行される可能性のある特定のトランザクションを超えて永続的なデータがあることです。もちろん、インスタンス変数を読み取り専用にすると、問題を回避できます。

その問題は、私にとって1年間多くのやり直しにつながりました。

于 2008-08-15T02:54:53.653 に答える
2

シングルトンの最大の問題は、特にテストを並行して独立して実行したい場合に、単体テストが困難になることです。

2 つ目は、ダブルチェック ロックを使用した遅延初期化が実装に適していると人々がよく信じていることです。

最後に、シングルトンが不変でない限り、アプリケーションをスケールアップして複数のプロセッサで複数のスレッドで実行しようとすると、簡単にパフォーマンスの問題になる可能性があります。競合同期は、ほとんどの環境でコストがかかります。

于 2008-09-16T10:55:57.993 に答える
2

会社に関するデータを保存/取得するための永続化レイヤーとの通信、従業員や価格コレクションの処理など、数十の責任があったため、仮装した単なる変数の集まりではありませんでした。

単一のオブジェクトであるべきものを実際に説明しているわけではなく、データのシリアライゼーションを除いて、それらのいずれかがシングルトンであるべきだったことは議論の余地があります。

私が通常設計するクラスのセットを少なくとも 3 つ見ることができますが、限られた一連のタスクを非常にうまく実行する、より小さく単純なオブジェクトを好む傾向があります。これはほとんどのプログラマーの性質ではないことを私は知っています。(はい、私は毎日 5000 行クラスの怪物に取り組んでおり、一部の人々が作成する 1200 行のメソッドが特に好きです。)

ポイントは、ほとんどの場合、シングルトンは必要なく、多くの場合、あなたの人生を難しくしているだけだということだと思います.

于 2008-08-15T05:22:48.177 に答える
1

私はSpringと組み合わせてシングルトンを何度も使用しましたが、松葉杖や怠惰とは考えていませんでした。

このパターンで可能になったのは、一連の構成タイプの値に対して単一のクラスを作成し、その特定の構成インスタンスの単一の(変更不可能な)インスタンスをWebアプリケーションの複数のユーザー間で共有することでした。

私の場合、シングルトンには、そのクライアントに固有のクライアント構成基準(cssファイルの場所、db接続基準、機能セットなど)が含まれていました。これらのクラスは、Springを介してインスタンス化およびアクセスされ、同じ構成のユーザー(つまり、同じ会社の2人のユーザー)によって共有されました。* **このタイプのアプリケーションの名前があることは知っていますが、それは私を逃れています*

アプリのユーザーごとに、これらの「定数」オブジェクトの新しいインスタンスを作成(次にガベージコレクション)するのは無駄だったと思います。

于 2008-08-27T18:14:06.783 に答える
1

シングルトンには用途がありますが、それらの使用と公開には注意が必要です。これは、悪用が容易であり、真の単体テストが困難であり、相互にアクセスする 2 つのシングルトンに基づいて循環依存関係を簡単に作成できるためです。

ただし、すべてのデータが複数のインスタンス間で同期されていることを確認したい場合に役立ちます。たとえば、分散アプリケーションの構成は、シングルトンに依存して、すべての接続が同じ最新のものを使用するようにする場合があります。データの日付セット。

于 2008-08-15T01:48:54.927 に答える
1

シングルトンを使用することに決めた理由について、非常に注意する必要があることがわかりました。他の人が述べたように、それは本質的にグローバル変数を使用するのと同じ問題です。あなたは非常に用心深く、それを使って何ができるかを考えなければなりません。

それらを使用することは非常にまれであり、通常はより良い方法があります。シングルトンで何かを行った後、コードをふるいにかけ、それがどれほど悪いことかを発見した後 (または、はるかに優れた、より健全な解決策を思いついた後) に遭遇しました。 )

于 2008-08-15T02:50:15.003 に答える
0

たとえばJavaのシングルトンで恐ろしいことの1つは、場合によっては同じシングルトンの複数のインスタンスになる可能性があることです。JVMは、クラスの完全修飾名と、そのロードを担当するクラスローダーの2 つの要素に基づいて一意に識別します。

つまり、互いに認識しない 2 つのクラスローダによって同じクラスがロードされる可能性があり、アプリケーションのさまざまな部分が、対話するこのシングルトンのさまざまなインスタンスを持つことになります。

于 2008-09-17T20:04:45.420 に答える
0

私は、仮装のアイデアにおける一連のグローバル変数については、まったく同意しません。シングルトンは、適切な問題を解決するために使用すると非常に便利です。実際の例を挙げましょう。

私は以前、自分が働いていた場所向けに小さなソフトウェアを開発しました。いくつかのフォームでは、会社、従業員、サービス、および価格に関する情報を使用する必要がありました。最初のバージョンでは、システムはフォームが開かれるたびにデータベースからそのデータをロードし続けました。もちろん、私はすぐに、このアプローチが最善の方法ではないことに気付きました。

次に、その場所に関するすべてをカプセル化したcompanyという名前のシングルトン クラスを作成し、システムが開かれるまでにデータで完全に満たされました。

会社に関するデータを保存/取得するための永続化レイヤーとの通信、従業員や価格コレクションの処理など、数十の責任があったため、仮装した単なる変数の集まりではありませんでした。

さらに、会社のデータを保持するための固定された、システム全体の、簡単にアクセスできるポイントでした。

于 2008-08-15T03:40:26.870 に答える
0

シングルトンは非常に便利であり、それを使用すること自体はアンチパターンではありません。ただし、主に悪い評判を得ているのは、それらとやり取りするために、消費するコードにシングルトンであることを認めるように強制するためです。つまり、それらを「非シングルトン化」する必要がある場合、コードベースへの影響が非常に大きくなる可能性があります。

代わりに、Singleton をファクトリの背後に隠すことをお勧めします。そうすれば、将来サービスのインスタンス化の動作を変更する必要がある場合、Singleton を使用するすべてのタイプではなく、ファクトリを変更するだけで済みます。

さらに良いことに、コントロール コンテナの反転を使用してください。それらのほとんどにより、インスタンス化の動作をクラスの実装から分離できます。

于 2008-09-15T17:24:18.210 に答える
0

通常の、テスト可能で、注入可能なオブジェクトを作成し、Guice/Spring などにインスタンス化を処理させます。真剣に。

これは、キャッシュの場合でも、シングルトンの自然な使用例が何であれ適用されます。1 つのインスタンスを強制しようとするコードを書くという恐怖を繰り返す必要はありません。依存性注入フレームワークに処理させてください。(軽量 DI コンテナーをまだ使用していない場合は、Guice をお勧めします)。

于 2009-02-18T19:25:37.570 に答える