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

Dependency injection 使用依赖注入还是有更简单的解决方案?,dependency-injection,dependency-management,Dependency Injection,Dependency Management,在我们的项目中,我们有一个KnowledgeBaseManager类,其他类使用该类,如下所示: KnowledgeBaseManager manager = KnowledgeBaseManager.get(); manager.foo(); KnowledgeBaseManager持有一个静态变量standardKnowledgeBaseManager,第一次使用时会初始化该变量: class KnowledgeBaseManager { private static Knowledg

在我们的项目中,我们有一个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

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

现在)不应因此而改变

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


我曾经考虑过使用依赖注入框架,比如PicoContainer或Guice,但是我没有任何使用它的经验,而且我不确定这是否会给这个特定的问题带来开销。对我们案例中的最佳实践有什么建议吗

您可以使用构造设计模式


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

您正在实现单例模式-如果您的代码是多线程的,那么您实现的是错误的(请参阅)

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

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

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

但是对于许多程序,您可能能够编写DI风格的代码,而不需要使用DI框架

 KnowledgeBaseManager manager = KnowledgeBaseManager.get(); 
public class ClassUsingKnowledgeBaseManager {

  protected final KnowledgeBaseManager knowledgeBaseManager;

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

  // ...

}