使用依赖注入还是有更简单的解决方案?

时间:2011-10-19 19:41:55

标签: dependency-injection dependency-management

在我们的项目中,我们有一个类KnowledgeBaseManager,它被其他类使用如下:

KnowledgeBaseManager manager = KnowledgeBaseManager.get();
manager.foo();

KnowledgeBaseManager包含一个静态变量standardKnowledgeBaseManager,它在第一次使用时会被初始化:

class KnowledgeBaseManager {
  private static KnowledgeBaseManager standardKnowledgeBaseManager = null;
  public static KnowledgeBaseManager get() {
    if (standardKnowledgeBaseManager == null) {
      standardKnowledgeBaseManager = new KnowledgeBaseManager();
      // initialize  standardKnowledgeBaseManager with appropriate knowledge base
    }
    return standardKnowledgeBase;
 }

此外,我们有一个参数化构造函数

public static KnowledgeBaseManager get(OntModel model) {...}
我们直到现在才使用

进行单元测试,我们需要一个在后台有测试知识库的KnowledgeBaseManager。

现在,我们面临以下挑战:对于开发,我们希望应用程序在后台使用具有另一知识库的KB管理器(因为速度)。更具体地说,我们使用Wicket构建Web应用程序。所以我们想在应用程序的开头声明某个地方,在应用程序中使用哪个知识库和KnowledgeBaseManager(取决于我们在开发或部署中)。使用KB管理器的代码(如

 KnowledgeBaseManager manager = KnowledgeBaseManager.get(); 

现在)不应该因此而改变。

问题是:什么是最好的架构?

我正在考虑使用像PicoContainer或Guice这样的依赖注入框架,但没有任何使用它的经验,我不确定这是否会成为特定问题的开销。我们的案例有关最佳实践的建议吗?

2 个答案:

答案 0 :(得分:2)

您正在实现单例模式 - 如果您的代码是多线程的,那么您实现它是错误的(请参阅http://java.sun.com/developer/technicalArticles/Programming/singletons/

此外,正如您所发现的,单身(即全局变量)用于测试。依赖注入是答案之一。首先忽略所有框架。这意味着您以传统的方式编写KnowledgeBaseManager--一个带有构造函数和方法的类,没有静态的单一因子方法。使用KnowledgeBaseManager的代码实例化或查找KnowledgeBaseManager-而是通过构造函数或setter方法接收它(我更喜欢前者):

public class ClassUsingKnowledgeBaseManager {

  protected final KnowledgeBaseManager knowledgeBaseManager;

  public ClassUsingKnowledgeBaseManager(KnowledgeBaseManager knowledgeBaseManager) {
    this.knowledgeBaseManager = knowledgeBaseManager;
  }

  // ...

}

请注意,鉴于该类不查找/实例化管理器,它不关心您是使用单例还是什么,并且您可以轻松地在测试中实例化不同的管理器,而无需以任何方式触及您的代码。

以这种方式构造代码之后,您可能会发现最终会出现一些丑陋的类,它们只是实例化您需要的所有对象,您需要一些额外的代码来将对象绑定到不同的范围(即会话或请求范围)对象)并使用配置文件来控制实例化...如果你发现你正在编写大量重复或样板代码,你可以查看DI框架,这可能会为你节省时间。

但是对于很多程序,你可以在不使用DI框架的情况下编写DI风格的代码。

答案 1 :(得分:0)

您可以使用结构设计模式。

您可以创建工厂并将其配置为返回所需的对象。