2011-12-21 23 views
9

私はシングルトンの嫌がらせではありませんが、虐待を受けていると私は知っています。シングルトンの使用を避けるための助けが必要

私はクロスプラットフォーム(Windows XP/Vista/7、Windows Mobile 6.x、Windows CE5、Windows CE6)になるアプリケーションを開発しています。このプロセスの一環として、私は、コードの重複を減らすために、コードを別々のプロジェクトに再組み込みしているため、インタルシステムの間違いを修正する機会があります。

別々に作られているアプリケーションのそのような部分は、非常にシンプルで、そのプロファイルマネージャです。このプロジェクトは、プロファイルの保存を担当します。これは、アプリケーションのすべての部分で使用されるいくつかの構成データを含むProfileクラスを持っています。それはProfilesを含むProfileManagerクラスを持っています。 ProfileManagerは、Profilesをハードドライブ上の別個のXMLファイルとして読み書きし、アプリケーションが "アクティブ" Profileを取得して設定できるようにします。シンプル。

最初の内部ビルドでは、GUIはアンチパターンSmartGUIでした。 MVC/MVPを使用しないWinForms実装でした。なぜなら、うまく設計されているのではなく、早く作業したいからです。これはシングルトンであるProfileManagerにつながります。これはアプリケーションのどこからでもそうだったので、GUIはアクティブなProfileにアクセスできました。

これは、私がちょうどProfileManager.Instance.ActiveProfileに行って、必要に応じてシステムのさまざまな部分の設定を取得できることを意味しました。各GUIはプロファイルを変更することもできるので、各GUIには保存ボタンがあるため、すべてがProfileManager.Instance.SaveActiveProfile()メソッドにもアクセスできました。

ここでシングルトンを使うのは間違いないと思うし、シングルトンが理想的ではないことも分かっているからだ。 これをより適切に処理する方法はありますか? ProfileManagerのインスタンスをすべてのコントローラ/プレゼンタに渡す必要がありますか? ProfileManagerが作成されると、他のコアコンポーネントが作成され、プロファイルが変更されたときにイベントに登録する必要があります。この例は非常にシンプルで、おそらく多くのシステムで共通の機能なので、シングルトンを回避する方法を学ぶには最適な場所だと思っています。

p.s.私は使用できる通常の.Net Frameworkクラスの多くを制限するCompact Framework 3.5に対してアプリケーションを構築する必要があります。

+6

私は自分の古い習慣で立ち往生しているかもしれませんが、シングルトンを使うべき良い例としてこれを見ています。 –

+0

これは実際にシングルトンインスタンスの理想的なケースのように聞こえます。 – msarchet

+0

すべての答えをありがとう、これはシングルトンを使用するための適切な場所と思われる。 Factory/Dependency Injectionについてのフィードバックは考慮されますが、このアプリケーションはバックグラウンドで実行されるため、シンプルさとパフォーマンスの両方でシングルトンとして残しておきます。 – JonWillis

答えて

8

シングルトンが悪用される理由の1つは、シングルトンがグローバル、共有、時には変更可能な状態のコンテナとして機能することが多いという理由の1つです。アプリケーションで実際にグローバルな共有状態にアクセスする必要がある場合は、シングルトンは非常に抽象的なものです。マイクやオーディオ再生にアクセスする必要のあるモバイルアプリでは、これを調整する必要があります。

アプリケーションの場合、アプリケーションのさまざまな部分を変更できる必要がある、単一の「アクティブな」プロファイルがあります。私はあなたが本当にこの抽象化に合っているかどうかを判断する必要があると思います。プロファイルの表記がディスク上の単一のXMLファイルであるとすれば、シングルトンとして持つのはいいと思います。

私はあなたがプロファイルマネージャを保持するために依存性注入またはファクトリパターンのどちらかを使うべきだと思います。あなたは、これの必要性を理解するためにプロファイルの使用を必要とするクラスの単体テストを書く必要があります。実行時にプログラムで作成されたプロファイルを渡すことができるようにする必要があります。そうしないと、コードはどこかのディスク上のXMLファイルに密接に関連した依存関係になります。

+0

部分的な書き直しは単体テストになりますが、私の強みではありませんが、私はまだTDDを学びます。テストされていないシングルトンはまだありますが、問題はそれらがインスタンス(メソッドまたはプロパティ)が静的であるため、簡単に嘲笑/スタブすることができないということです(静的メソッドはオーバーライドできません)生成されたクラスのサブクラスは嘲笑される)。 – JonWillis

2

「シングルトン」は、「グローバル」変数を置き換えるために本質的に使用されている場合、実際には悪いことです。この場合、それがそれが使用されているものであれば、とにかくシングルトンであるとは限りません。

あなたが記述した場合、実際には理想的です。アプリケーションがプロファイルマネージャを必要とするすべての人に利用可能であることをアプリケーションが確かめることができ、アプリケーションの他の部分は、既存のものと競合します。これにより、1つのインスタンスを回して不要な参照を余分に保持しようとしているところで、余計なパラメータやフィールドがどこでも削減されます。ただ1つのインスタンシエーションに強制されている限り、私はそれに間違いを感じません。

シングルトンは、複数のインスタンス化と「エントリ」の単一ポイントを避けるように設計されています。それがあなたが望むものなら、それは行く方法です。それが十分に文書化されていることを確認してください。

+0

あなたの意見をお寄せいただきありがとうございます。私は "シングルトン"と単なる "単一参照"を持たないことに懸念を抱いています。最終的には面倒なビジネスになります。 – JonWillis

5

あなたのProfileManager用のインターフェースを用意し、そのインスタンスをそれを使用する各ビュー(または何か)のコンストラクターに渡すことをお勧めします。こうすることで、シングルトンやスレッド/ユーザー/などのインスタンスを簡単に持つことができます。また、データベース/ Webサービスなどに行く実装を持つこともできます。

また、ProfileManagerを使用するすべてのものに直接アクセスするのではなく、ファクトリを呼び出すこともできます。その後、そのファクトリはインスタンスを返すことができます。また、シングルトンでもなくてもかまいません(データベースやファイルやWebサービスなどに行きます)。ほとんどのコードは知る必要はありません。

あなたの直接の質問には答えませんが、将来の変化がゼロに近い影響を与えます。

+0

私はインターフェースを考えましたが、それに対して決定されたProfileManagerのタイプはこれまでに1つしかないことが分かっていました。ファクトリメソッドを使用する方法もありますが、とにかくシングルトンを返すコードを追加したいと思っているので、私はそれを提案することを躊躇していますが、実装が変更された場合はすべてのパーツではなく、そのシングルトンを使用するコードの乾杯。 – JonWillis

関連する問題