java - 一个简单的 IOC 容器类有什么问题?

标签 java architecture inversion-of-control ioc-container testability

最后一天,我在我的一个 Playground 项目中实现了一个简单的类来充当 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)

代码处理控制反转,没有任何紧密耦合(使用接口(interface))。

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

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

残忍地杀了我吧:D

最佳答案

总结评论轨迹:

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

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

控制反转的基本思想/目标是通过减少依赖关系来减少耦合,如果您的容器依赖于服务实现(需要直接调用构造函数),则不会发生这种情况。因此,您问题中的实现在某种程度上违背了这一基本思想。

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

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

注册表通常伴随着一些配置注册表的方法,例如通过配置文件或类路径扫描(自动查找存在的插件)。但是,仅编写一些配置注册表的代码也可能就足够了。这完全取决于您需要消除什么耦合(以解决您面临的问题)以及哪种耦合是可以接受的。

关于java - 一个简单的 IOC 容器类有什么问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50695434/

相关文章:

java - 如何用Java实现HTTP请求队列

c# - IoC 和 ASP.NET MVC Controller

c# - 是否可以覆盖 CaSTLe Windsor 3 中的命名注册?

java - 从 CSS/JS 文件中访问 servlets web 应用程序上下文 URL

java - 在 Freemarker 中遍历两个序列

java - WBXML 解析器/解码器

java - 通过 block 和其他参数使用 HttpUrlConnection 发送图像

c - 如何将偏移量添加到程序计数器?

python - 鸭子类型(duck typing)实践 - Python 3.7

java - Spring根据请求值使用不同的bean