- 5 -- 5 -
1. 入门:依赖注入——传统的组件耦合方式
public class Depositor {
private Bank bank;
private DepositBook depositBook;
public Cash withDraw(BigDecimal amount) {
bank = new BankFactory().createBankICBC(); // 工厂创建依赖
depositBook = new DepositBookFactory().createDepositICBC();// 工厂创建依赖
return bank.withDraw(depositBook, amount);
}
}
public class BankFactory {
public Bank createBankICBC() {
return new BankICBC("Tianjin", 100);
}
}
public class DepositBookFactory {
public DepositBook createDepositICBC() {
return new DepositBookICBC("62202", "current", "CNY");
}
}
工厂模式工厂模式
- 6 -- 6 -
1. 入门:依赖注入——传统的组件耦合方式
工厂模式工厂模式
但是随着软件工程的不断复杂化和规模化,工厂模式同样的遇到了很多问题
而被开发人员诟病。围绕着这个话题的讨论有很多,我们不再一一列举,只
举一个比较常见的问题来说明一下。假设我们的银行不只有工商银行,还有
招商银行、中国银行等等,这样就需要我们维护一个越来越庞大的工厂类。
之前的 Bank 工厂就要逐渐这样增加 create 方法:
public class BankFactory {
public Bank createBankICBC() {
return new BankICBC("Tianjin", 100);
}
public Bank createBankCMB() { // …… };
public Bank createBankBOC() { // …… };
// ……
}
- 7 -- 7 -
1. 入门:依赖注入——传统的组件耦合方式
工厂模式工厂模式
这样工厂类自身的维护成本逐渐增大,就成为了工厂模式的一个很大的障碍。
因此很多开发者想办法用参数化的形式,来减少工厂类的维护量。
public class BankFactory {
public Bank createBank(BankVender bankVendor) { // 参数化的工厂方法
switch (bankVendor) {
case ICBC:
return createBankICBC();
case CMB:
return createBankCMB();
default:
return createBankICBC();
}
}
// ……
}
但是这样一来又会回到手工 new 对象的一个问题,即如果工厂方法的参数发
生了变化,可能会引起全部调用到该工厂方法的代码都需要修改及做相应的
回归测试。
- 8 -- 8 -
Service
Locator
容器
Service
Locator
容器
1. 入门:依赖注入——传统的组件耦合方式
ServiceLocatorServiceLocator 模模
式式
某储户类某储户类
get
get
public class Depositor {
private Bank bank;
private DepositBook depositBook;
public Cash withDraw(BigDecimal amount) {
bank = (Bank) new ServiceLocator().get("BankICBC");
depositBook = (DepositBook) new ServiceLocator().get("DepositBookICBC");
// 从 ServiceLocator 容器中获取依赖对象
return bank.withDraw(depositBook, amount);
}
}
“BankICBC”
“DepositBookICBC”
ServiceLocator ,即服务定位器,实质
上是一种改进版的工厂模式。这种模式
的核心思想是,将构建依赖的接口彻底
与依赖者分离,并将此依赖作为“服务”
绑定到一个标识符(通常是一个字符
串),而后依赖者则可通过这个标识符
获取被绑定的依赖。
- 10 -- 10 -
1. 入门:依赖注入——传统的组件耦合方式
但是 ServiceLocator 模式最大的弱
点就是,依赖对象的获取强依赖于
ServiceLocator 容器,除非开发者
愿意花费大量成本自己实现
ServiceLocator 容器,否则就必须
要中间件提供商的支持,这就给我们
的开发和测试带来了很大困扰,因为
往往各个厂商的对标识符的命名方式
都很不一样,使得开发者很不容易获
得到所需要的依赖对象。
ServiceLocatorServiceLocator 模模
式式
Service
Locator
容器
Service
Locator
容器
“ ???”
“ ???”
get
get
Get what?Get what?
- 11 -- 11 -
1. 入门:依赖注入——“依赖注入”登场
于是诸多优秀的 IT 工程师开始想出了更加轻量便利、更加具有可测试性和可
维护性的设计模式—— IoC 模式。 IoC ,即 Inversion of Control 的缩写,
中文里被称作“控制反转”。至于为什么会有这么一个看似古怪的名字,我们
稍后会做解释。 2004 年著名软件工程学者和工程师 Martin Fowler 在其论
文《 Inversion of Control Containers and the Dependency Injection
pattern 》中将 IoC 更名为 Dependency Injection ,从此依赖注入模式成
为实现组件间松耦合的主流设计思想。