【问题标题】:How to choose between methods of acquiring dependencies?如何在获取依赖的方法之间进行选择?
【发布时间】:2011-03-31 18:00:06
【问题描述】:

我已经看到了至少三种在 Java 对象中获取依赖项而不将对象与依赖项的创建耦合的方法;

依赖注入 - 某些框架基于外部配置将所需对象注入到另一个对象中,例如:Spring 托管 bean

依赖查找 - 类在某种目录服务中查找所需的依赖项,例如:Java EE 容器中的 JNDI 查找

静态工厂 - 全局范围内的对象按需提供实例 - 标准 Java SE API 似乎充斥着这些,例如:java.util.Logger.getLogger(name)、java.util.Calendar.getInstance()

对于哪种情况最适合您提供哪些指导?

【问题讨论】:

  • 澄清一下,依赖注入并不需要框架和外部配置,你可以编写一个例程来创建你想要的实例并在需要的地方注入它们。当然,如果您需要更改任何内容,则需要重新编译(这就是框架和外部配置的来源)。
  • 我强烈建议您在 SO 中搜索相关的问题和答案——这是一个老生常谈的领域。例如,查看Dependency Injection & Singleton Design Pattern,或访问ploeh blog。
  • @Jeff Sternal 感谢您提供问题链接,我错过了那个!

标签: java dependency-injection static-factory


【解决方案1】:

我更喜欢依赖注入,因为对象不需要知道它如何获取它需要的引用。

依赖查找仍然需要对象知道查找服务及其 URL。

静态工厂类似于查找服务。

【讨论】:

  • 有什么东西困扰着我,想把它固定下来!这可能是一个愚蠢的例子,但如果我们使用类似 log4j 的东西,将不同的 Logger 实例注入到每个类中是否有吸引力/可行?如果不是这个用例有什么不同,还有比静态工厂更好的方法吗?
  • 对于log4j,并没有真正的好处——您很少需要更改类使用的记录器/名称。相反,log4j 的设计方式是,您可以根据需要配置命名记录器以执行不同的操作,即将com.something.MyClass 记录器的输出发送到文件或数据库,而不是而不是给com.something.MyClass一个文件或数据库记录器的实例。
  • 当然可行;这就是为什么像 slf4j 这样的框架突然出现的原因,它是多个日志框架的适配器,因此它们可以更好地与容器、spring 等集成。
  • 记录的不是经典的 AOP 示例吗?为什么要在每个类中注入一个 Logger?
【解决方案2】:

我更喜欢依赖注入。

当我用 Spring Framework 谈论 DI 时,我看到以下内容

  1. IDE 支持(错误检查、可视化)。
  2. 您可以设置其他需要的东西,例如 AOP、属性加载……
  3. 您有很大的配置可能性 - XML、注释、JavaConfig
  4. 也可以在桌面应用程序中使用。

这些平衡了所有负面因素,例如对另一个库的依赖。为什么我应该使用另一种方法?

【讨论】:

    【解决方案3】:

    这真的取决于上下文。如果您正在编写一个自包含的数学 API,您可能希望使用静态工厂,因为代码将不那么冗长、无需设置并且可能更高效。如果您需要访问/提供远程依赖项,则 JNDI/LDAP 查找或 ESB 消息传递会很好地工作。要将您的服务/DAO/数据源注入您的典型企业服务器代码,您最好使用常见的 D.I. 之一。 Google Guice 或 Spring 等框架。

    软件设计中没有单一的“最佳”解决方案;这总是一个权衡。

    【讨论】:

      猜你喜欢
      • 2015-01-07
      • 1970-01-01
      • 2011-11-26
      • 2019-12-17
      • 2019-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-09
      相关资源
      最近更新 更多