如何处理OO应用程序中的跨领域问题? 使用Singleton? dependency injection? 什么?

假设我正在设计一个应用程序,我需要使用全局计时系统(这是一个跨领域的问题)。 我需要从我的应用程序的任何地方访问来自该全球计时系统的数据,并且我不能看到“应用程序的这部分需要它而另一部分不需要”。

我的问题是..我应该将其设计为一种环境语境(在这种情况下,单身人士),还是应该尝试设计其他方式来适应这种情况?

我当然不认为让我的所有类必须通过构造函数注入将这个全局计时类传递给它们是正确的。 很多时候我必须将参考文件真正传递到链中,直到某些类最终需要它。 另一方面,从阅读的角度来看,它会使一切变得更加清晰(它清楚地说明了我的类的依赖性)。

人们通常如何处理这个问题? 有没有其他技术可以帮助解决这个问题? AOP可能吗?

PS:全球计时系统只是我从一本我正在阅读的书中获取的一个想法。 日志系统将是这类问题的另一个很好的例子。

谢谢

正如您所建议的那样, 面向方面编程(AOP)的设计考虑到了这一点,所以我当然会检查出来。

虽然构造函数注入在这种情况下似乎很麻烦,但使用IOC容器可能有助于减轻您的痛苦。 单身确实看起来很合适,但由于静态性,它们带来了可测试性问题 – 但是你可以通过将它分成两部分来解决这个问题。

我用aop做了什么:

public abstract aspect AutoInjectAspect { /** * Implemented by the concrete class to decide what value to return. * @param joinPoint * @return */ abstract public T getInjectedValue(JoinPoint joinPoint); protected pointcut autoInjectField() : get(@AutoInject T *); /** * override the "get" of the otherwise null value with the * value to be injected * @return the injected field */ T around(): autoInjectField() { return getInjectedValue(thisJoinPoint); } } 

然后提出了具体方面:

public aspect SLF4jLoggerInjector extends AutoInjectAspect { @Override public Logger getInjectedValue(JoinPoint joinPoint) { Class classInjected = joinPoint.getStaticPart() .getSignature().getDeclaringType(); Logger logger = LoggerFactory.getLogger(classInjected); return logger; } }
public aspect SLF4jLoggerInjector extends AutoInjectAspect { @Override public Logger getInjectedValue(JoinPoint joinPoint) { Class classInjected = joinPoint.getStaticPart() .getSignature().getDeclaringType(); Logger logger = LoggerFactory.getLogger(classInjected); return logger; } } 

然后制作一个注释“@AutoInject”并将其放在要注入的字段上。

话虽这么说,你也可以是IOC集装箱航线。

无论你是否将它作为单例实现,我仍然建议你通过dependency injection传递它。 我还建议你不要自己实现单独的东西,并遵循一个DI框架,为你提供一个单一的IOC库所做的单例上下文。

如果每个人都需要它并且它是独一无二的(就像你提到的日志一样),它绝对是一个单身人士。

我认为你是对的,有些类型不适合构造函数注入; 有时你需要以比一组对象更广泛的方式跟踪某种上下文。

当我遇到这个问题时,我会经常创建一个Singleton,但是让初始化逻辑调用dependency injection框架来进行实际的实例化。 这导致了对特定静态方法的耦合(有些人会反对这一点) – 但同时我可以随意改变实现(也许对于某些类型在测试项目中有不同的实现,或者其他的东西)。 而且我得到的好处是不必在所有对象构造函数之间传递一个非常常见的类型。

当然,你应该只在很多地方需要这种类型时才这样做。 否则,使用普通的构造函数注入。 确切地说,“没关系”由你来决定。

一个静态单例类就是我在大多数时候看到它的方式。 使用日志记录作为一个更常见的跨领域问题,我总是看到我的日志记录调用如下所示:

 public class SomeClassThatDoesStuff { private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); public void DoStuff() { log.Info("Doing something"); } } 

你是全球时间课程似乎是一种类似的交叉问题,我会以同样的方式接近它

我同意用DI做这件事会很乏味而且不是非常务实。