我经常混淆这三个术语,它们对我来说非常相似。有人能否用例子清楚地向我解释它们。我看过类似的帖子,但仍不完全明白。
例如,你可以从以下内容开始:
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
是AccountManager
的依赖项,而AccountManager
是AdminConsole
的依赖项。然后,AdminConsole
需要将DbConnection
实例传递给AccountManager
,而AccountManager
需要将其传递给UserFetcher
......即使AdminConsole
和AccountManager
都不需要直接使用DbConnection
!
控制反转容器(Spring、Guice等)旨在通过自动连接(提供)依赖项来使依赖注入更加简单。为此,您只需告诉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
时,DbConnection
会自动提供。策略模式
只是依赖注入的一个特殊情况,其中您注入的是逻辑而不是对象(即使在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;
}