将横切关注点注入类中的有哪些不同的方法,以便在保持代码可测试(TDD或其他)的同时最小化所涉及的类的耦合?
例如,考虑我是否有一个需要记录功能和集中式异常管理的类。我应该使用DIP并通过接口将所需的关注点注入需要它们的类中吗?我是否应该使用我传递给每个需要一些交叉功能的类的服务定位器?是否有完全不同的解决方案?我完全问错了问题吗?
答案 0 :(得分:24)
Decorator设计模式是实施跨领域关注点的绝佳起点。
首先,您需要定义一个为相关服务建模的界面。然后,您可以实现该服务的真实功能,而无需考虑您的跨领域问题。
然后,您可以随后实现包装其他实例的装饰类,并实现所需的交叉关注。
这种方法可以完全用普通的旧C#对象(POCO)实现,不需要额外的框架。
但是,如果你厌倦了编写所有额外的装饰器,你可能想要使用一个框架。我没有使用显式AOP框架的经验,但是大多数DI容器(例如Castle Windsor)提供了类似AOP的功能。
以下是使用装饰器的示例。假设您有以下界面:
public interface IMyInterface
{
void DoStuff(string s);
}
您的具体实现可能会做一些非常有趣的事情,例如将字符串写入控制台:
public class ConsoleThing : IMyInterface
{
public void DoStuff(string s)
{
Console.WriteLine(s);
}
}
如果您希望记录DoStuff操作,现在可以实现一个日志记录器:
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);
}
}
你可以继续编写新的装饰器,比如缓存装饰器或实现安全性的装饰器等,然后将它们包裹起来。
注意:我很少推荐静态接口,因此Log.Write接口不是推荐,而只是作为占位符。在真正的实现中,我会在LoggingThing中注入某种ILogger接口。
答案 1 :(得分:4)
您可以使用Observer模式。
主体拥有一组观察者。当主体执行操作时,它会通知观察者更改。然后,观察者可以在主体不关心该动作的情况下执行动作。
以下是一个例子:
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.");
}
}
我已经习惯了Java,所以请原谅任何语法错误。