2009-11-10 8 views
24

コードをテスト可能(TDDなど)に保ちながら関連するクラスの結合を最小限に抑えるために、クロスカッティング問題をクラスに注入するさまざまな方法は何ですか?クロスカッティングの懸念事項を注入するためのさまざまな方法は何ですか?

たとえば、ログ機能と集中例外管理の両方を必要とするクラスがあるとします。私はDIPを使用し、両方の必要な問題をインタフェースを介してそれらを必要とするクラスに注入する必要がありますか?クロスカット機能を必要とする各クラスに渡すサービスロケータを使用する必要がありますか?まったく別のソリューションがありますか?私は間違った質問を完全に求めていますか?

答えて

23

Decoratorデザインパターンは、クロスカッティングに関する懸案事項を実施するための優れた出発点です。

まず、問題のサービスをモデル化するインターフェイスを定義する必要があります。それでは、クロスカッティングに関する懸念を全く考慮せずに、そのサービスの本当の機能を実装します。

次に、他のインスタンスをラップする装飾クラスを実装し、希望するクロスカッティングの問題を実装できます。

このアプローチは、Plain Old C#Objects(POCO)で完全に実装することができ、余分なフレームワークを必要としません。

ただし、すべての余分なデコレータの作成に飽きた場合は、フレームワークを使用することができます。明示的なAOPフレームワークに関する経験はありませんが、Castle WindsorのようなほとんどのDIコンテナはAOPのような機能を提供します。


デコレータの使用例を次に示します。あなたは次のインタフェースを持っているとしましょう:あなたはDoStuff操作をログに記録したい場合は、

public class ConsoleThing : IMyInterface 
{ 
    public void DoStuff(string s) 
    { 
     Console.WriteLine(s); 
    } 
} 

public interface IMyInterface 
{ 
    void DoStuff(string s); 
} 

あなたの具体的な実装には、コンソールに文字列を書き込むなど、非常に興味深い何かをすること

public class LoggingThing : IMyInterface 
{ 
    private readonly IMyInterface innerThing; 

    public LoggingThing(IMyInterface innerThing) 
    { 
     this.innerThing = innerThing; 
    } 

    public void DoStuff(string s) 
    { 
     this.innerThing.DoStuff(s); 
     Log.Write("DoStuff", s); 
    } 
} 
あなたは、キャッシングデコレータかそこらのセキュリティを実装し、1、およびちょうどWRのように、新しいデコレーターを書き続けることができ

:あなたは今、ロギングデコレータを実装することができますそれらをお互いの周りにap。

注:静的インターフェイスはほとんどお勧めできません。そのため、Log.Writeインターフェイスはお勧めできませんが、単にプレースホルダとして意味します。実際の実装では、私はLoggingThingにILoggerインターフェースのいくつかを注入します。

+0

私はデコレータも考慮しました。メソッドを簡潔にしておけば、私が提案したソリューションの例から期待されるコントロールの細かさを犠牲にすることはありません。 デコレータを好む理由はありますか?デコレーションされたクラスはクロスカッティングの問題を認識する必要がないためです。 –

+0

これは、あなたがそれらを扱うときに懸念を横断するためのあなたの好ましい解決策ですか? –

+0

私は実際の実装をきれいにきれいに保つので、戦略の注入に比べてDecoratorを優先します。私はしばしばそれを好むが、時折、例えば、ウィンザー城。 –

4

Observerパターンを使用できます。

件名はObserversのコレクションです。サブジェクトがアクションを実行すると、オブザーバに変更が通知されます。オブザーバーは、そのアクションが何であるかを気にする主題なしにアクションを実行できます。私は構文エラーを許してください、Javaへの慣れ

public interface IThingObserver 
{ 
    void Notify(); // can also pass in a parameter with event information 
} 

public class Thing 
{ 
    private readonly ICollection<IThingObserver> observers; 

    public Thing() 
    { 
     observers = new List<IThingObserver>(); 
    } 

    public void RegisterObserver(IThingObserver observer) 
    { 
     observers.Add(observer); 
    } 

    public void UnregisterObserver(IThingObserver observer) 
    { 
     observers.Remove(observer); 
    } 

    private void NotifyObservers() 
    { 
     foreach (IThingObserver observer in observers) 
     { 
      observer.Notify(); 
     } 
    } 

    public void DoIt() 
    { 
     Console.WriteLine("Doing it..."); 
     NotifyObservers(); 
    } 
} 

public class LoggingThingObserver : IThingObserver 
{ 
    public void Notify() 
    { 
     Log.Write("It is done."); 
    } 
} 

は、ここでの例です。

+0

私は元々09年にこれを作ったことは知っていますが、答えに感謝します!オブザーバーは、OCPとの懸念やヒットを切り離すのに役立つ良い勧告です。 –