2012-05-02 5 views
9

シングルトンについての議論が多々あり、それがなぜ悪いのかが分かります。それはこの質問についてではありません。私はシングルトンの欠点を理解しています。私はシングルトンの代わりにデザインをしたい

シングルトンを使用するのが簡単で意味があるように見えるシナリオがあります。しかし、私は大量のオーバーヘッドなしに必要なものを達成するための代替手段が必要です。

私たちのアプリケーションは通常、現場のラップトップで実行され、バックエンドサーバーと通信するクライアントとして設計されています。メインアプリケーションの下部にステータスバーがあります。さまざまな彫像や情報だけでなく、いくつかのアイコンを表示するいくつかのテキスト領域が含まれています。アイコンは、その状態を示すためにイメージを変更します。接続されているかどうかを示すGPSアイコン、エラー状態など。

メインクラスはMobileMainです。これは、ステータスバー領域を所有し、それを作成する責任があります。その後、StatusBarManagerクラスが作成されます。 StatusBarManagerは現在静的クラスですが、シングルトンでもあります。ここにクラスの始まりがあります。

public static class StatusBarManager 
{ 
    static ScreenStatusBar StatusBar; 

    /// <summary> 
    /// Creates the status bar that it manages and returns it. 
    /// </summary> 
    public static ScreenStatusBar CreateStatusBar() 
    { 
     StatusBar = new ScreenStatusBar(); 
     return StatusBar; 
    } 

MobileMainはStatusBarManagerに対してStatusBarを要求します。その後、StatusBarを使用します。その他のクラスは、StatusBarを見るだけで、StatusBarManagerはありません。

ステータスバーの更新は、アプリケーションのどこからでも行うことができます。ステータスバーのテキスト領域とアイコン状態を更新する追加のクラスを更新できるクラスは約20種類あります。

ステータスバーとステータスバーマネージャはそれぞれ1つだけです。

より良い実装のための提案はありますか?

私が持っていたいくつかの考え:

はStatusBarManagerインスタンスクラスを作成します。私のMobileMainクラスでは、StatusBarManagerクラスの静的パブリックインスタンスを保持します。ステータスバーの更新を行うには、MobileMain.StatusBarManager.SetInformationTextまたはマネージャの他のメソッドを呼び出します。 StatusBarManagerはシングルトンではありませんが、MobileMainは静的インスタンスを作成するだけです。ここでの問題は、MobileMainがStatusBarとStatusBarManagerを持ち、StatusBarが所有するStatusBarだけを管理することです。 StatusBarManagerには、世界的に利用可能な静的インスタンスがあります。

もう1つのアイデアは、EventEggregatorクラスのようなものを使用することでした。私は一度も使ったことはありませんが、それらについて読んだことがあります。私は、それが世界的に利用可能なクラスであることをコンセプトにしていると思います。ステータスバーを更新したい各クラスでは、StatusBarUpdateイベントを発行します。 StatusBarManagerは、StatusBarUpdateイベントをサブスクライブする唯一のクラスであり、すべての通知を受け取ります。私はあなたがオブジェクトをクリーンアップするときにイベントからの登録を忘れることに注意していなければ、この方法でリークを起こすことがありますが、これを読んだことがあります。このアプローチは検討する価値がありますか?

+1

この投稿には多数の質問があります。一度に1つずつ選んで回答を得てください。 – mydogisbox

+0

あなたはMEFまたはUnityの使用について考えましたか?そこで、コンテナに必要なものを1つだけ登録して、他の場所から取得することができます。 – stijn

+0

StatusBarManagerの命名に関連した良い読書。 http://www.codinghorror.com/blog/2006/03/i-shall-call-it-somethingmanager.html – Patrick

答えて

2

StatusBarクラスまたはStatusBarManagerクラスを持つかどうかは大きな問題ではありません。しかし、あなたのアプリケーションで多くのクラスをStatusBarsとStatusBarManagersについて知っていることは悪い考えです。強いカップリングを引き起こし、おそらく痛みを感じます。

どのようにですか?

現在ステータスバーにステータスを報告しているコンポーネントは、 - ステータスを報告するためにテキストコンソールを使用する別のアプリケーションで再利用する必要があるとします。 - ステータスを複数の場所に報告しますか? または - ステータスはまったく報告されません。

ベスト代替: - イベントリスニング。クラスのStatus Changedイベント(コールバックを使用できます)を公開するか、クラスに共通する既存の共有リソースを公開します。あなたのステータスバーのような他のパーティーは、イベントを購読することができます。そしてあなたが言及したように、定期購読がもはや必要/有効でなくなったときにはいつでも、退会する必要があります。

- WPFの場合、依存関係プロパティ 'StatusText'を持つWPFにタグを付けたので、このアプローチでは複数のステータスプロパティがある場合には、今あなたのステータスバーに表示される必要がある最も興味深いステータスを教えてください!バインディング、マルチバインディング(ブリーチ、複雑さ)、または依存関係プロパティの変更イベントハンドラがあります。

しかし - 私は可能な限りあなたのUI層に限定DependencyObjectsとDependencyPropertiesを保つためにあなたを助言します。その理由は、UIスレッド上のDispatcherに暗黙的に依存しているため、UI以外の雑用には簡単に適応できないからです。

あなたのアプリの多くの部分があるので、いくつかの1つの場所ともう1つの場所を使用して、これらの両方を組み合わせることは妥当であるかもしれません。

+1

答えをありがとう。私はあなたの最善のアプローチの理解を明確にしたかったのです。ステータスバーを更新する各クラスにStatusChangedイベントを配置する必要があります。そのイベントを発生させ、ステータスバーにそれをサブスクライブします。これはあなたが示唆していることですか?その場合、StatusBarまたはStatusBarManagerはStatusChangedイベントに登録できるように、それを更新するすべてのクラスの知識が必要です。私はすべてのクラスでStatusBarManagerの知識を持って再利用できるようにすることで問題を理解していますが、その理由の1つは変更を加えたいからです。 – WPFNewbie

+0

私はNotificationManagerを使用することも考えていました。これは共有リソースの提案に該当する可能性があります。ステータスバーを含むすべての通知を処理できます。理想的なことは、インタフェースを持つことです。そのため、クラスはINotifierインタフェースを実装したクラスを持っている限り、どのプロジェクトでも再利用できますが、シングルトンや静的クラスではできないと思います。 – WPFNewbie

+0

ああ - 良い点があります - ステータスバーは実際にすべてのクラスについて知る必要はありません!代わりに、StatusBar.UpdateStatus()メソッドを持ち、上位レイヤークラス(それ以外の理由ですべてのことを知っているクラス)でバインドを行い、すべてのイベントハンドラーがそのメソッドを呼び出すようにすることができます。 –

3

私はあなたのオブジェクトを保持する静的クラスを優先します。したがって、アクセス可能なオブジェクトの量は、静的クラスが提供するインタフェースによって再調整されます。アプリケーションがまだスケールしている限り、Staticは悪くありません。

シングルトンのもう1つの良い代替方法は、シングルトンの動作を表すためのプライベート静的フィールドを実装するクラスを持つMonostateパターンです。

参照:
Monostate
Monostate vs. Singleton

がUPDATE: それは多くの場合でも、内部のプログラム構造のために、心の中でのAPIのようなRESTを保つために私を助けます。 1つのクラスがどこからでも更新され、すべての人に通知を送信することは、条件と無限ループを発生させるために制御するのが難しいです(更新 - >イベント - >更新 - > ...)

必要な場所にアクセスできるステータスバーのインターフェイス。そのようなテクニックを使用する場合は、ステータスバーのインターフェイスにアクセスするための静的クラスを使用します(小規模プロジェクトには推奨されません)。あなたのステータスバーのインターフェイスへのすべての呼び出しは、状況の改善に関するさらなる問題を避けるために、ステータスバーによって生成される可能性のあるイベントから独立していなければなりません。情報をプッシュしてプルするためにプログラムの他の部分から呼び出すことができるウェブサイトのようなステータスバーのインターフェースを考えてみてください。

+0

要約すると、StatusBarManagerが静的クラスである現在の設計者に間違いはありませんか?あなたが含む他のリンクを見ました。モノスタットに関しては、私がそれを透明にしたくないという問題があります。ステータスバーが1つしかないことを知っている必要があります。それはとにかく私の気持ちです。静的クラスとシングルトンの主な問題は、それらを参照するクラスの再利用性です。これで、別のプロジェクトでクラスを再利用した場合、充足しなければならないグローバルクラスへの参照ができました。 – WPFNewbie

+0

通常、静的に「悪いこと」があります。多くのクラスがいくつかの静的クラスに依存しているため、リファクタリングとテストが不可能になります。 ステータスバーが静的ではなく、ステータスバーへのインターフェイスが静的である場合でも、ステータスバーは引き続きテストケースに交換できます。静的クラスは、必要に応じて静的クラスを書き換えるために十分に小さくなります。 – Tarion

+0

静的クラスを取り除きたい場合は、依存性注入(プロパティまたはコンストラクタ注入)のみを可能性として表示します。コンストラクターインジェクションでは、コンストラクターごとにStatusBar(またはStatusBarHandler)が必要になります。 PropertyInjectionは、プロパティを挿入するという事実に依存します。これは通常、MicroKernelによって行われます。プログラム全体がそのカーネルに依存します。テスト可能なコードが必要な場合は、DIは良い方法ですが、デバッグするのが難しいため、小さなプロジェクトで混乱させる可能性があります。 – Tarion

-1

それは、アプリケーションのアーキテクチャの多くを知らなくても助言を与えるのは難しいですが、おそらくあなたは、依存性注入を検討すべきです。たとえば、StatusBarインスタンスを直接使用する各クラスのコンストラクタに渡します。

+0

これは大まかな考えのようです。これで、構築時にすべてのオブジェクトに余分なパラメータを渡し、初期化するためにコンストラクタに余分なコードを追加し、オブジェクト全体にオブジェクトを追加して、実際に単一のオブジェクトであるオブジェクトへの参照を多く格納し、 StatusBarタイプなしでコンパイルすることはできません。 –

1

単純にObserverパターンを使用して、StatusBarをリスナーとして20個のオブジェクトに追加することができます。これにより、シングルトンが排除され、SRPとDIPの方が優れていますが、その努力に値するかどうかを検討する必要があります。間接指示があまりにも複雑になり、依存関係の注入が不可能な場合、シングルトンはより良いかもしれません。

public class StatusBar implements StatusListener { 
} 

public interface StatusListener { 
    public statusChanged(String newStatus) 
} 
0

クラスは、任意のuse singletonに明示的に依存し、コンストラクタの任意のパラメータに明示的に依存します。シングルトンにインターフェイスを追加することをお勧めします。必要なメソッドだけがIStatusBarを使用してクラスに公開されます。これはよりコードですが、単体テストが楽になります。

関連する問題