0

.NET/C# のバックグラウンドを持ち、PRISM に精通しCompositionContainerているため、必要なときにクラスのインスタンスを 1 つだけ取得するというアイデアがとても気に入っています。

このインスタンスを介してServiceLocatorグローバルにアクセスすることもできるため、これはシングルトン パターンに相当します。

現在、私の現在のプロジェクトは c++ であり、プログラムのプラグイン (外部 dll の読み込みなど) を管理する方法を決定する段階にあります。

C# では、PluginService を作成し、それを共有としてエクスポートし、その 1 つのインスタンスを介してすべてをチャネルします (メンバーは基本的に、プラグインと一連のメソッドを保持する 1 つのリストだけになります)。CompositionContainerC++ では明らかに aまたは aがありませんServiceLocator

おそらくこれの基本的なバージョンを実現することができますが、私が想像するものには、シングルトンまたはグローバル変数を使用することが含まれます。ただし、これに関する一般的な懸念は次のように思われます。グローバルを決して実行しないでください。

どうしようかな?(そして、私が興味を持っているのは、ここで Microsoft がコーディング方法の悪い例を示しているのか、それともシングルトンが正しい選択であるという実際のケースなのか?)

4

2 に答える 2

6

グローバルとシングルトンが「良い」か「悪い」かという点では、C# と C++ の間に違いはありません。

あなたが概説した解決策は、C# と C++ の両方で等しく悪い (または良い) ものです。

あなたが発見したように見えるのは、単に人によって意見が異なるということです。一部の C# 開発者は、このような目的でシングルトンを使用することを好みます。一部の C++ プログラマーも同じように感じています。

一部の C++ プログラマーは、シングルトンはひどいアイデアだと考えており、一部の C# プログラマーは同じように感じています。:)

Microsoft は、コーディング方法の多くの悪い例を示しています。ボックスに Microsoft と書かれているという理由だけで、サンプル コードを「グッド プラクティス」として決して受け入れないでください。重要なのはコードであり、その背後にある名前ではありません。

さて、シングルトンに関する私のメインビーフは、シングルトンのグローバルな側面ではありません。

ほとんどの人と同じように、私は一般的にグローバルを嫌い、信用していませんが、絶対に使用すべきではないとは言いません。何かをグローバルにアクセスできるようにした方が便利な場合があります。それらは一般的ではありません (ほとんどの人はまだグローバルを使いすぎていると思います) が、存在します。

しかし、シングルトンの本当の問題は、コードに不必要で、しばしば有害な制約を課すことです: オブジェクトの複数のインスタンスを作成することを妨げます。実際のユーザーが行います。

コメントで述べたように、たとえばクラスを作成するときは、それをどのように使用する予定PluginServiceであるかについてある程度のアイデアがあります。おそらく、「そのインスタンスはグローバルにアクセス可能であるべきです (多くのクラスは pluginservice にアクセスすべきではないため、議論の余地がありますが、今のところグローバルにたいと仮定しましょう)」と考えているでしょう。なぜ 2 つのインスタンスが必要なのか想像してみてください。」

しかし、問題は、この仮定を採用して、2 つのインスタンスの作成を積極的に防止する場合です。

今から 2 か月後に、2 つの PluginServices を作成する必要があることに気付いたらどうしますか? クラスを作成したときに簡単な方法を選択し、不必要な制約をクラスに組み込まなかった場合は、簡単な方法を選択し、単純に 2 つのインスタンスを作成することもできます。

しかし、複数のインスタンスが作成されるのを防ぐために追加のコードを記述するという困難な道をたどった場合は、再び困難な道をたどらなければなりません。戻ってクラスを変更する必要があります。

理由がない限り、コードに制限を組み込まないでください。作業が簡単になる場合は、先に進んで実行してください。クラスの有害な誤用を防ぐことができるのであれば、それを実行してください。

しかし、シングルトンの場合、それらのどちらも行いません。完全に正当な使用を防ぐために、自分で余分な作業を作成します。

シングルトンの質問に答えるために私が書いたこのブログ投稿を読むことに興味があるかもしれません。

しかし、特定の状況をどのように処理するかという特定の質問に答えるには、次の 2 つのアプローチのいずれかをお勧めします。

  • 「純粋主義者」のアプローチは、グローバルServiceLocatorではないを作成することです。サービスを見つける必要がある人に渡します。私の経験では、これは思ったよりもはるかに簡単であることがわかるでしょう。あなたが思っていたほど多くの異なる場所では、実際には必要ではないことに気付く傾向があります. また、コードを分離し、依存関係を最小限に抑え、ServiceLocator を本当に必要としている人だけがアクセスできるようにする動機を与えてくれます。それは健康です。
  • または実用的なアプローチがあります: の単一のグローバル インスタンスを作成しますServiceLocator。それを必要とする人は誰でもそれを使うことができ、それを見つける方法に疑いの余地はありません。結局のところ、それはグローバルです. ただし、シングルトンにしないでください。他のインスタンスを作成できるようにします。別のインスタンスを作成する必要がない場合は、単純に作成しないでください。ただし、これによりドアが開いたままになるため、別のインスタンスが必要になった場合に作成できます

1 つのインスタンスしか必要ないと思っていたクラスの複数のインスタンスが必要になる状況は数多くあります。一部のハードウェアの構成/設定オブジェクト、ロガー、またはラッパーはすべて、「これは明らかにシングルトンであるべきであり、複数のインスタンスを持つことは意味がありません」と人々がよく言うものであり、これらの各ケースでは、それらは間違っています. そのようなクラスの複数のインスタンスが必要な場合が多くあります。

しかし、最も普遍的に適用可能なシナリオは単純にテストです。

ServiceLocator が機能することを確認します。だからあなたはそれをテストしたい。

それがシングルトンの場合、それは本当に難しいです。優れたテストは、以前のテストの影響を受けない、手付かずの隔離された環境で実行する必要があります。ただし、シングルトンはアプリケーションの期間中存続するため、ServiceLocator の複数のテストがある場合、それらはすべて同じ「ダーティ」インスタンスで実行されるため、各テストは次のテストで見られる状態に影響を与える可能性があります。

代わりに、テストはそれぞれ新しいクリーンな ServiceLocator を作成する必要があるため、テストがどの状態にあるかを正確に制御できます。そのためには、クラスのインスタンスを作成できる必要があります。

したがって、シングルトンにしないでください。:)

于 2012-08-24T11:19:04.900 に答える
1

適切な場合、シングルトンに問題はまったくありません。私は疑問を持っていますCompositionContainer(しかし、それが実際に何をすべきかを理解しているかどうかはわかりません)が、 ServiceLocatorよく設計されたアプリケーションでは一般的にシングルトンになるようなものです。2 つ以上ServiceLocator あると、プログラムが正常に機能しなくなります (サービスがそのうちの 1 つに登録され、別のサービスを検索するため)。少なくとも堅牢なプログラミングを好む場合は、これをプログラムで強制することは肯定的です。さらに、C++ では、初期化の順序を制御するためにシングルトン イディオムが使用されます。シングルトンを作成しない限り ServiceLocator、静的な有効期間を持つオブジェクトのコンストラクターで使用することはできません。

非常に声高な反シングルトン狂信者の小さなグループがありますが、より大きな C++ コミュニティ内では、特定の非常に限られたケースでは、コンセンサスがシングルトンを支持していることがわかります。それらは簡単に悪用されます (ただし、テンプレート、動的割り当て、ポリモーフィズムも同様です) が、特定の問題を非常にうまく解決します。問題。

于 2012-08-24T12:44:21.023 に答える