一个简单的 IOC 容器有什么问题 class?

whats wrong with a simple IOC container class?

最后一天我在我的一个 playground 项目中实现了一个简单的 class 作为 IOC 容器(不太像),一些专业人士告诉我在测试代码时会遇到一些问题(太静脉分享到底是什么问题!!)

虽然我自己一直使用 IOC 框架,但我想知道为什么这种方法不好?

我什至使用这种方法编写了很多测试(使用模拟框架)并且从未遇到过问题。

我想要你关于这个设计问题的想法:

public class IocContainer{

  private static IocContainer instance;

  private IocContainer(){
  }

  public static IocContainer getInstance()
  {
    if(instance == null){
      instance = new IocContainer();
    }
    return instance;
  }

  public ChatPresenter getChatPresenter(ChatView chatView)
  {
    return new ChatPresenterImpl(chatView, getChatRepo() , getMessagingService());
  }

  private ChatRepo getChatRepo()
  {
    return new ChatRepoImpl(getDbHelper(), getRemoteService());
  }

  private MessagingService getMessagingService()
  {
    return new MessagingServiceImpl()
  }

  private DbHelper getDbHelper()
  {
    return new DbHelperImpl();
  }

  private RemoteService getRemoteService()
  {
    return new RemoteServiceImpl();
  }
}

如您所见,我只使 getChatPresenter 可访问,我在我看来如下使用它并且效果很好。

ChatPresenter presenter = IocContainer.getInstance().getChatPresenter(this)

代码在没有任何紧密耦合(使用接口)的情况下处理控制反转。

我想知道这种方法有什么问题吗? (我想从技术角度回答,因为我已经知道使用 Ioc 容器库更容易,它具有更多功能,例如作用域等...)

其实我想知道这种方法在未来会带来什么问题和限制?

残忍点杀了我:D

总结评论线索:

您的方法看起来像 Martin Fowler 在此处描述的服务定位器:http://martinfowler.com/articles/injection.html#InversionOfControl

Martin 描述的内容与您的代码之间存在重大差异:您的代码直接创建服务的实例,因此与其说是注册中心,不如说是工厂。

控制反转的基本 idea/goal 是通过减少依赖性来减少耦合,如果您的容器依赖于服务实现(它需要直接调用构造函数),则不会发生这种情况。所以你问题中的实现有点反对这个基本想法。

依赖于实现的缺点之一是如果不重新编译容器就无法替换服务。如果您很可能永远不会有不同的实现,那可能不是问题,但如果您可能需要它,服务 registry 会更有用。

注册表通常提供注册服务实现并根据请求提供服务的方法。交付哪个取决于您的需求,但它可能与找到的第一个实现一样简单,也可能更复杂,例如通过匹配一些参数(如需一些想法,请查看 CDI 注入点参数和备选方案)。

注册中心一般都会附带一些配置注册中心的手段,例如通过配置文件或类路径扫描(自动查找存在的插件)。但是,仅编写一些配置注册表的代码也可能就足够了。这完全取决于你需要摆脱什么样的耦合(以解决你面临的问题)以及哪种耦合是可以接受的。