依赖注入:良好的老式重构有什么问题?

时间:2010-03-26 21:55:47

标签: java refactoring dependency-injection

DI创建了一个额外的抽象层,这样如果您的实现类发生了变化,您可以简单地使用相同的接口插入另一个类。

但是,当你想使用不同的实现类时,为什么不简单地重构呢?像Python和Ruby这样的其他语言也很好用。为什么不用Java?

3 个答案:

答案 0 :(得分:13)

这是依赖注入的错误表征。并不是你有一个特定接口的实现随着时间的推移而变化;相反,可能会同时存在许多不同的接口实现,并且将使用哪种实现可以在程序的多个不同运行中变化。例如,在您的实际程序中,您可能希望使用一个实现,而在单元测试期间,您可能希望使用更易于测试的替代版本“模拟”该实现。在这种情况下,重构不是解决方案,因为您需要能够在不中断开发过程的其余部分的情况下始终进行测试。

还应该注意,依赖注入通常用作Singleton反模式的解决方案;它允许一个人拥有一个单例对象,可以在测试过程中轻松模拟出来。而且,如果后来证明单例假设确实不正确,那么单例可以被各种实现替换。

您可能会发现一些有助于更好地理解该主题的资源:

答案 1 :(得分:0)

所以你说Python和Ruby不能有依赖注入?或者如果没有DI,Java无法正常工作?

除了你错过了最具特色的DI之外,你可以拥有动态DI,不仅仅是在编译时,而是在运行时。在软件工程中总是存在一个问题:抽象太多而且太少而且实际上归结为你如何为问题设计解决方案

答案 2 :(得分:0)

不完全。这里的问题是当你编写一个代码片段时:

Runnable r = new MyFooRunnable();

你基本上决定你需要的Runnable是MyFooRunnable(而不是MyBarRunnable或第三个)。有时您会希望将该决定从编译时间推迟到部署时间,以便部署人员可以决定应用程序所包含的各个模块是如何粘合在一起的。< / p>

传统上这已经完成了工厂,但这只是在代码中移动实际的决定,你仍然必须知道编码工厂时的所有可能性或让它从配置文件中读取指令(这往往对重构很脆弱。)

依赖注入是一种配置工厂的形式化,因此代码不需要知道任何有关工作方式的信息。这也是为什么注释被发现对指出依赖注入应该发生的位置非常有用的原因。如果在非DI设置中运行代码(如junit测试),那么就不会发生任何事情(这对于几乎遍布的工厂很难做到。)

因此,使用的依赖注入允许您编写“快速”捕获的模块,而无需在编译时相互了解。这与jar文件概念非常相似,但它需要更长时间才能成熟。