グローバルとシングルトンが「良い」か「悪い」かという点では、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 を作成する必要があるため、テストがどの状態にあるかを正確に制御できます。そのためには、クラスのインスタンスを作成できる必要があります。
したがって、シングルトンにしないでください。:)