回答
依赖注入指的是告诉类的依赖关系是什么样的模式,而不是要求类知道在哪里找到它的所有依赖关系。
因此,举例来说,你从这个去:
public class UserFetcher {
private final DbConnection conn =
new DbConnection("10.167.1.25", "username", "password");
public List<User> getUsers() {
return conn.fetch(...);
}
}
到这样的事情:
public class UserFetcher {
private final DbConnection conn;
public UserFetcher(DbConnection conn) {
this.conn = conn;
}
public List<User> getUsers() {
return conn.fetch(...);
}
}
这降低耦合的代码,这是非常有用的,如果你想进行单元测试UserFetcher
。现在,您可以将DbConnection
传递给测试数据库,而不是运行10.167.1.25
的数据库,而不是UserFetcher
总是。或者,在快速测试中更加有用,您可以传入一个DbConnection
的实现或子类,它甚至不连接到数据库,它只是丢弃请求!
但是,这种原始依赖注入使得布线(提供与它的依赖的对象)更加困难,因为你已经替换为使依赖访问使用全局变量(本地实例化的对象或)的依赖性围绕整个对象图。
想象一下UserFetcher
是AccountManager
的依赖关系,其依赖于AdminConsole
。然后AdminConsole
需要的DbConnection
实例传递给AccountManager
,并AccountManager
需要将它传递给UserFetcher
... 即使没有AdminConsole
也不AccountManager
需要直接使用DbConnection
!
控制容器的反转(春,吉斯等)的目的是通过自动布线(提供)的依赖关系,使依赖注入容易。要做到这一点,你告诉你的IoC容器一次如何提供一个对象(在Spring中,这称为bean),并且每当另一个对象请求该依赖关系时,它将由容器提供。
所以我们的最后一个例子可能看起来像这样与吉斯,如果我们使用构造器注入:
public class UserFetcher {
private final DbConnection conn;
@Inject //or @Autowired for Spring
public UserFetcher(DbConnection conn) {
this.conn = conn;
}
public List<User> getUsers() {
return conn.fetch(...);
}
}
我们必须要配置的IoC容器。在Guice中,这是通过执行Module
完成的;在Spring中,通常通过XML配置应用程序上下文。
public class MyGuiceModule extends AbstractModule {
@Override
public void configure() {
bind(DbConnection.class).toInstance(
new DbConnection("localhost", "username", "password"));
}
}
现在,当UserFetcher
由吉斯或Spring构造时,DbConnection
被自动提供。
Guice有a really good Wiki article关于依赖注入背后的动机,并进一步使用IoC容器。这是值得一读的。
的策略模式是依赖注入,在那里你注入逻辑而不是一个对象(即使在Java中,逻辑将在对象封装)的一个特例。这是一种解耦独立业务逻辑的方式。
例如,你可能有这样的代码:
public Currency computeTotal(List<Product> products) {
Currency beforeTax = computeBeforeTax(products);
Currency afterTax = beforeTax.times(1.10);
}
但是,如果你想这个代码扩展到一个新的司法管辖区,以不同的销售税方案?您可以注入计算税的逻辑,如下所示:
public interface TaxScheme {
public Currency applyTax(Currency beforeTax);
}
public class TenPercentTax implements TaxScheme {
public Currency applyTax(Currency beforeTax) {
return beforeTax.times(1.10);
}
}
public Currency computeTotal(List<Product> products, TaxScheme taxScheme) {
Currency beforeTax = computeBeforeTax(products);
Currency afterTax = taxScheme.applyTax(beforeTax);
return afterTax;
}
控制反转意味着运行时框架将所有组件连接在一起(例如Spring)。依赖注入是IoC的一种形式(我不知道是否存在另一种形式的IoC)(请参见:http://en.wikipedia.org/wiki/Inversion_of_control)。
策略模式是一种设计模式(由GoF定义),其中算法可以被另一个替换(参见:http://en.wikipedia.org/wiki/Strategy_pattern)。这是通过提供几个相同接口的实现来存档的。当使用类似Spring的IoC时,如果您有多个接口实现,并且您可以通过配置从实现切换到另一个实现,那么您正在使用策略模式。
我也推荐阅读关于这个问题的Spring文档的介绍章节: Introduction to Spring Framework
前几段应该做的。
这也链接到:Inversion of Control Containers and the Dependency Injection pattern
这也提供了这些非常重要的核心概念的动机观点。
- 1. 策略模式和依赖注入
- 2. C#依赖注入和策略模式
- 3. 策略模式vs依赖注入
- 4. 在依赖注入中使用策略和工厂模式
- 5. 使用Unity的策略模式和依赖注入
- 6. AngularJS中的依赖注入和控制反转
- 7. 使用POJO控制和依赖注入的反转
- 8. 控制的依赖注入和反转 - 术语
- 9. 在MVC中通过依赖注入学习控制反转3
- 10. 控制反转,依赖注入瓦特/ SRP和延迟加载
- 11. C#MongoDb依赖注入和控制反转
- 12. 控制容器反转与依赖注入模式之间的区别
- 13. 依赖注入控制器@
- 14. 序列化依赖注入配置/控制反转
- 15. 是否存在分层方法来控制依赖注入/控制反转
- 16. 依赖注入和观察者模式
- 17. 依赖注入和/或工厂模式
- 18. 使用依赖注入MVC 3控制器的命令模式
- 19. 什么是依赖注入用户输入的最佳策略?
- 20. 控制反转或依赖注入 - 任何人在C中执行它?
- 21. 依赖注入最佳实践和反模式
- 22. 策略设计模式中不同具体策略之间的依赖关系?
- 23. 在使用依赖注入的同时实例化控制器
- 24. 在这个例子中通过@Produce注释的依赖注入
- 25. Nugetpacked库中的控制反转 - 传入依赖关系
- 26. 工厂模式在依赖注入
- 27. 依赖注入和模型控制器相互了解
- 28. CodeIgniter和依赖注入/控制器注入
- 29. Laravel结构 - 依赖注入控制器
- 30. Laravel控制器依赖注入