可能な重複:
シングルトンの悪いところは何ですか?
多くのデザインパターンが悪用される可能性があることは理解できます。ママがいつも言っているように、「良いことが多すぎると必ずしも良いとは限りません。「
私は最近、シングルトンを多用していることに気づいています、そして私は自分自身でデザインパターンを悪用し、そして悪い習慣の種類のより深く実行するかもしれないことを心配しています。
ユーザーが作業している間、非常に大きな階層データ構造をメモリ内に保持するFlexアプリケーションを開発しています。ユーザーはオンデマンドでデータをロード、保存、変更、更新することができます。
このデータは、いくつかのArrayCollections、Array、valueオブジェクト、およびゲッターとセッターを介して公開される他のネイティブメンバー変数を集約するSingletonクラスによって一元管理されます。
アプリケーション内のどこからでも私たちのデータへの参照を得るために、私たちはModel.getInstance()メソッド全体のことをします。設計時に、アプリケーションの存続期間中に存在できるインスタンスは1回だけであると説明していたため、これにより、常に同じデータのコピーを確実に手に入れることができます。
この中央データリポジトリから、たとえばプロパティ変更イベントを送出し、中央データを参照する複数のUIコンポーネントを持ち、発生したデータ変更を反映するように表示を更新することができます。
これまでのところ、このアプローチは効果的であり、私たちの状況にとって非常に実用的であることが証明されています。
しかし、私は新しいクラスを作成するとき、私はちょっとやり過ぎだと思っています。クラスがシングルトンであるべきか、あるいはファクトリを使用しているような別の方法で管理されるべきかというような質問は、少々不確実性を伴いながら、時々少し困難になる傾向があります。
シングルトンでどこに線を引くのですか?シングルトンをいつ使用するか、またいつ使用しないかを決定するための適切なガイドラインがありますか。
また、デザインパターンに関する優れた本を誰かが推薦できますか?
覚えておくべき重要なことは、デザインパターンは抽象概念を理解するのを助けるための単なるツールであるということです。理解した後は、本の中の「レシピ」に限定することは無意味であり、自分の目的に最も適したコードを書くことができなくなります。
とは言っても、GoFのような本を読むことは問題を考えるためのより多くの方法をあなたに提示するでしょう。
あなたの場合、シングルトンを使うことがすべての場合に意味があるならば、それからすぐに先に行きなさい。それが「種類の」適合し、あなたがそれを何らかの不格好な方法で実装しなければならないならば、あなたは新しい解決策を思いつく必要があります。完璧ではないパターンを強制することは、丸い穴に四角い釘を打つのと似ています。
「このアプローチは効果的であり、私たちの状況にとって非常に実用的であることが証明されています」とあなたが言うことを考えると、私はあなたがうまくやっていると思います。
ここにいくつかの良い本があります:
4冊のギャング - デザインパターンの古典的な本
ヘッドファーストデザインパターン - これは代替手段として少数の人々によって推奨されていると聞いた
はい、シングルトンは悪いです。彼らがあなたのためにするのは2つの特性を結合することだけであるのでそれらは悪いです、それぞれの特性は時間の約95%悪いです。 (これは、平均して、シングルトンの99.75%が悪いことを意味します。)
GoFで定義されているシングルトンは、次のようなデータ構造です。
最初のものは一般的に悪いことと考えられています。グローバルは好きではありません。 2番目の方法はもう少し微妙ですが、一般的にこれが合理的な制限であるケースはほとんどありません。実施する。
場合によっては、オブジェクトのインスタンスを1つ持つことだけが意味があります。その場合は、作成することを選択します強制するためにシングルトンは必要ありません。
そして、通常、インスタンスが1つしかないことが「理にかなっている」場合でも、結局意味をなさないことがわかります。遅かれ早かれ、あなたは複数のロガーが必要になるでしょう。または複数のデータベースまたは、単体テストごとにリソースを再作成する必要があるため、それらを自由に作成できる必要があります。結果を理解する前に、コードから柔軟性を時期尚早に取り除いています。
シングルトンは依存関係を隠し、結合を高めます(すべてのクラスがシングルトンに依存する可能性があります。つまり、すべてのシングルトンを再利用しない限り、クラスは他のプロジェクトで再利用できません)。 )、それらに気づかないし、通常それらを作成するときそれについて考えない。ただシングルトンを引き込むのはとても簡単です、それはほとんどローカル変数として、そしてすべてのように振る舞います、それで我々は彼らがそこにいたら一度それらをたくさん使う傾向があります。そしてそれはそれらを再び除去することをほとんど不可能にします。あなたは、おそらくスパゲッティコードではなく、スパゲッティディペンデンシーグラフで終わるでしょう。遅かれ早かれ、あなたの暴走した依存関係はシングルトンがお互いに依存し始めることを意味するでしょう、そしてそれから1つが初期化されようとすると循環依存関係を得るでしょう。
それらはユニットテストを非常に難しくします。 (シングルトンオブジェクトの関数を呼び出す関数をどのようにテストしますか?実際のシングルトンコードを実行したくないのですが、どうすればそれを防ぐことができますか?)
はい、シングルトンは悪いです。
時々、あなたは本当にグローバルが欲しいです。次にシングルトンではなくグローバルを使用します。
ごくまれに、クラスのインスタンスを複数作成するとエラーになることがあります。できるエラーを引き起こすことなく実行することはできません。 (私が考えることができる唯一のケースについて、そしてそれが人為的に考えられているとしても、あなたが何らかのハードウェアデバイスを代表しているならば。あなたは1つのGPUしか持っていない。存在できるインスタンスは1つだけです)。しかし、もしあなたがそのような状況(そして繰り返しになりますが、「複数のインスタンスのユースケースを考えることができない」という状況だけでなく、複数のインスタンスが重大なエラーを引き起こす状況)にいるのなら、この制約はありますが、オブジェクトをグローバルに表示することもしません。
これら二つの特性のそれぞれできるまれに便利です。しかし、私は単一のケースを考えることはできません。組み合わせそれらのうちの良いことでしょう。
残念ながら、多くの人が「シングルトンはOOPに準拠したグローバルだ」という考えを持っています。いいえ、そうではないです。彼らはまだグローバルと同じ問題を抱えている、加えてまったく関係のない他のものを紹介すること。普通のグローバルよりシングルトンを好む理由は絶対にありません。
ソフトウェア開発者は、理想的なコーディングスタイルと実用的なコーディングスタイルのどちらを好むかに応じて、2つのキャンプにかなり均等に分割されているようです。
個人的には、私は実用的なアプローチを好みます。規則を破ることが理にかなっていることもありますが、それは自分がしていることを本当に理解していて、関連するリスクを受け入れても構わないという場合に限られます。あなたがあなたの特定のユースケースに関して以下の質問に「はい」と答えることができるならば、シングルトンパターンはいくつかの実用的な利益を生み出すことができます。
unsafe
そしてgoto
ほとんどの場合、まだどちらも.NET自体のソースコードで半頻繁に使用されています。すべての選択肢の長所と短所を知っていて、それでもシングルトンを使用することにした場合は、それで問題ありません。 - Abion47
シングルトンはプログラムを殺しません、プログラマーはプログラムを殺します。
他のプログラミング構成体と同様に、適切に使用された場合、あなたは自分の足を撃たないでしょう。
推奨されている本は問題ありませんが、シングルトンを使用することを選択する可能性がある場合の経験に付随する十分な背景を常に提供するわけではありません。
複数のインスタンスを持つ必要があるときにシングルトンが不適切な選択であることがわかったときに初めてその経験が得られます。突然、オブジェクト参照を至る所にインジェクトするのは大変なことになります。
場合によっては、先に進んでオブジェクト参照を配置したほうがよいですが、Singletonをまったく使用しているという事実は、別の設計にリファクタリングしなければならない場合に直面する問題の範囲を特定するのに役立ちます。これは非常に良いことだと思います。つまり、クラスがまったく設計されていなくても、クラスを作成するだけで、クラスへの変更の効果を確認できるようになります。
私たちは基本的に同じ質問に直面しているというプロジェクトを始めました。モデルにアクセスするそして、特にそのルート要素。このプロジェクトはFlexアプリではなく、遊びです。 Webアプリですが、それは問題ではありません。
を持っている単一オブジェクトシステムで結構です、問題はアクセス方法。だからシングルトンについての議論はの概念に関連しています依存性注入(DI)、およびオブジェクトの入手方法
DIの主な引数は以下のとおりです。
DIのための可能なアプローチは(古典を見なさい記事ファウラーから):
この観点では、シングルトンパターンは単なる一種のサービスロケータです。Model.getInstance()
。
しかし、将来の変化に備えて最大限の柔軟性を提供するためには、固有のオブジェクトへの参照を次のようにします。回った可能な限り多くのModel.getInstance()
必要なときだけ。これにより、コードがよりきれいになります。
私の意見では、シングルトンの使用は直接設計上の欠陥を示しています。その理由は、単にC ++に組み込まれている通常のオブジェクト作成および破棄メカニズムを回避することを許可しているからです。あるオブジェクトが別のオブジェクトへの参照を必要とする場合は、構築時にそのオブジェクトへの参照を渡すか、または内部でそのオブジェクトの新しいインスタンスを作成する必要があります。しかし、シングルトンを使用すると、作成と破棄のサイクルが明示的に難読化されます。関連する問題は、シングルトンの寿命を制御することが非常に難しいということです。その結果、一般的なシングルトン実装を含む多くのパッケージは、不格好なオブジェクトライフタイムマネージャなども含みます。シングルトンを管理するためだけにこれらが存在しないのではないかと思うこともあります。
基本的に、オブジェクトをさまざまな場所で使用する必要がある場合は、オブジェクトをスタック内の最も高い共通点に明示的に作成し、それを使用するすべての人に参照を介して渡します。複数の引数を新しいスレッドに渡すのに問題があるためにシングルトンを使用することがありますが、これには該当せず、スレッド引数を明示的に定義して同じ方法で新しいスレッドに渡します。あなたはあなたのプログラムがずっときれいに流れ、静的な初期化依存関係や誤ったティアダウンによる厄介な驚きがないことに気付くでしょう。
シングルトンは確かに悪くないです。彼らは彼らの用途を持っています、それらのいくつかはとても良いです。シングルトンは最初に学んだ設計パターンであることが多く、経験が浅い開発者にとっては使い過ぎになりがちで、かなり単純なので、意味を考えずにいたるところで使用されています。
シングルトンを使用したいときはいつでも、なぜそれをしているのか、そしてこのパターンを使用することの利点と欠点は何かを考えてみてください。
シングルトンはグローバルにアクセス可能な 'もの'(データかメソッドのどちらか)のセットを効果的に作成します、そして私はほとんどの人があまりにも多くのグローバル変数を使うのは素晴らしい考えではないと思うと思います。クラスとオブジェクト指向の重要な点は、すべてを1つの巨大なグローバル空間にまとめるのではなく、物事を個別の領域にまとめることです。
シングルトンよりも好みがちな 'パターン'の1つは、必要なオブジェクトを上から下に渡すことです。私はアプリの初期化段階でそれらを一度作成し、それらにアクセスする必要があるすべてのオブジェクトを通してそれらを渡します。これは、シングルトンパターンの「単一作成」部分を模倣していますが、「グローバル」部分はありません。
シングルトンの要点は、1つしか存在しないはずのオブジェクト用だということです。あなたはクラスのデータコントロールセットに言及します。おそらく、実際には、アプリが2セットのデータコントロールクラスを作成したい場合があるので、これにシングルトンを適用するのはまったく正しくないかもしれません。代わりに、これらのデータクラスをapp initで作成して渡した場合は、現在のアプリに必要なものは1セットのみ作成されますが、2つ目のセットが必要な場合はいつか可能性があります。簡単に作成できます。また、データコントロールクラスが本当にアプリ内のどこからでもアクセス可能にグローバルになっているはずです。私はそうは思わない、代わりにそれらはおそらく低レベルのデータアクセス層からのみアクセス可能であるべきです。
何人かの人々はGOF本を推薦しました。はい、それは素晴らしい本ですが、最初に一般的なアーキテクチャに関する本を試してみて、2/3 / n層の設計、カプセル化、抽象化、そしてこれらの種類の原則についてまず読んでください。これにより、GOFが話しているパターンの適切な使用方法を理解するためのより強固な基盤が得られます。
[編集:シングルトンバリアントが役に立つことがある他の時はあなたが何かへの単一のアクセスポイントが欲しいときですが、実装の詳細は実際には複数のことがあります。呼び出し側は、シングルトンオブジェクトに対するそれらの要求が実際にはいくつかの利用可能なオブジェクトに対して解決され、1つが返されることをカバーの下で知る必要はありません。私はここでスレッドプールのようなものを考えています。ここでは用途があります、ちょっと、ただ私にスレッドを取ってください、私は1を必要とします、しかし私はどちらを気にしません]
私はこれが古いスレッドであることを知っていますが、誰もOPがやろうとしていたことに合う実際のパターンについて言及しているようには見えませんでした。彼が必要としていると私が信じているものは、メディエータパターン。 SourceMakingは、この種の情報を学習/参照するための素晴らしいサイトです。確かに私はソフトウェアのパターンを人々に紹介する場所に行きます。また、どんなデザインパターンも必然的に善または悪であるという考えに没頭しないことが一般的には良い考えです。それらはすべて彼らの用途を持っています、それはいつ、どこでそれらを使うべきかを学ぶことがトリックです。私にはシングルトンを使用しないと言う人は、その有用性を理解していません。
シングルトンは「それほど悪い」というわけではありません。もしあなたがたくさんの関連するシングルトンを持っていて、あなたがあなたが気にするものを失うことなく、ファクトリーを使ってそれらの多くを交換/統合することができるなら、それはあなたがそうすべき時です。
本に関しては、まあ、一種の規範があります。
グーグルは確信しているそのシングルトンは悪い考えです。
それは、Googleがすることすべてが完璧であること、または彼らのすべての意見が議論の終りであることを示唆するものではありませんが、それらを根絶するためにこのシングルトン検出器を書くことまで行ってきました。あなた自身の決心をしなさい。