控制反转
此条目需要精通或熟悉相关主题的编者参与及协助编辑。 |
控制反转(英文缩写为IoC),也叫做依赖注入(Dependency Injection)。简称DI。是一个重要的面向对象编程的法则来削减计算机程序的耦合问题。
起源
早在2004年,Martin Fowler就提出了“哪些方面的控制被反转了?”这个问题。他总结出是依赖对象的获得被反转了。基于这个结论,他为控制反转创造了一个更好的名字:依赖注入。许多非凡的应用(比HelloWorld.java更加优美,更加复杂)都是由两个或是更多的类通过彼此的合作来实现业务逻辑,这使得每个对象都需要,与其合作的对象(也就是它所依赖的对象)的引用。如果这个获取过程要靠自身实现,那么如你所见,这将导致代码高度耦合并且难以测试。
IoC 亦称为 “依赖倒置原理”("Dependency Inversion Principle") (Martin 2002:127)。差不多所有框架都使用了“倒置注入(Fowler 2004)技巧,这可说是IoC原理的一项应用。SmallTalk,C++, Java 或各种.NET 语言等面向对象程序语言的程序员已使用了这些原理。
控制反转是Spring Framework的核心。
应用控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用,传递给它。也可以说,依赖被注入到对象中。所以,控制反转是,关于一个对象如何获取它所依赖的对象的引用,这个责任的反转
Technical description
术语
Class X 依赖于 class Y 只在如下状况中成立:
- X 拥有 Y 的控制并且在 X 中使用 Y
- X 是 Y 的派生物
- X 依赖于 Z,而 Z 又依赖于 Y (transitivity)
X 依赖于 Y 并不表示 Y 也依赖于 X。但如果 X 和 Y 同时依赖于对方,这种依赖性被称作 循环依赖:这时,X 无法和 Y 分开单独使用,反之亦然。如果在一个面对对象程式中拥有太多的循环依赖,这可能表示这个程式是个欠佳的设计。
打破依赖
如果类X的一个实例对象x调用了类Y的一个实例对象y的方法,那么就称类X依赖于类Y。为了打破这种依赖——“反转”,首先我们可以引入一个接口I(第三方类),接口I中声明了对象y将被对象x调用的所有方法;然后,我们对类Y稍加改造,使其实现接口I;最后,我们把在对象x中对y的调用改为对接口I中对应方法的调用。经过这番改造后,原先的X对Y的依赖关系不存在了,类X和Y现在都依赖于接口I。
这种通过引入接口I来消除类X对Y的依赖的方法,被称作“控制反转”,又叫做“依赖注入”。
需要注意的是,类Y可能还依赖于其他类。在应用反转之前,X依赖于Y,从而也间接依赖于Y所依赖的所有“其他类”。应用控制反转之后,不仅X对Y的直接依赖,且前面提到的那些所有的间接依赖也消除了。而新引入的接口I则不依赖于任何类。
IoC 的类型
Martin Fowler 将 IoC 分成三类。
- Type 1 : 基于interface (interface injection)。Depending object 需要实作(implement) 特定 interface 以供框架注入所需物件。
- Type 2 : 基于setter (setter injection)。Depending object 需要实现特定 setter 方法 (但不需要依赖特定interface),
- Type 3 : 基于constructor (constructor injection)
有框架,如Plexus 提出Type 4 IoC, 以field为基础,惟此法到目前为止尚未被广泛接纳。[1]
各种框架不一定支援以上所有IoC类型。例如SpringFramework 支援Type 1, Type 2及 Type 3 IoC, 而 Plexus支援 Type 2, Type 3 和 Type 4。
控制反转应用实例
C++
- PocoCapsule IoC and DSM framework GPL开源的,支持完全非侵入C++的控制反转(IoC)及领域特定建模(DSM)容器
Java
Programmers using the Java programming language have applied Inversion of Control in an Inversion of Control Container (Martin 2004). The software requests an object from the container and the container builds the object and its dependencies. The ATG Dynamo application server was one of the first environments to leverage this approach, while more recent examples of these containers include HiveMind, PicoContainer, Spring Framework (note that Spring is a complete enterprise platform, not just an IOC container), Apache Excalibur, Seasar, and DPML Metro.
.NET
相关信息
参考文档
- ^ Robert Cecil Martin. Agile Software Development: Principles, Patterns and Practices. Pearson Education. 2002. ISBN 0-13-597444-5.
- ^ Robert Cecil Martin. The Dependency Inversion Principle (PDF). [2005-11-15].
- ^ Martin Fowler. Inversion of Control Containers and the Dependency Injection Pattern. 2004 [2005-11-15].
- ^ Sony Mathew. Examining the Validity of Inversion of Control. 2005 [2005-11-16].
- ^ Ke Jin. Domain Specific Modeling (DSM) in IoC frameworks. 2007 [2007-11-13].
外部连接
- Another description of IOC
- A list of "Open Source Inversion of Control Containers"
- A simple demo of Inversion of Control (using Spring framework)
- Inversion of Control Containers and the Dependency Injection pattern by Martin Fowler
- Needle, a dependency injection (inversion of control) container for Ruby
- Drip IoC, a dependency injection (inversion of control) container for PHP4
- PyContainer, a dependency injection (inversion of control) container for Python
- Qt Ioc Container, a dependency injection (inversion of control) container for C++
- Introducing Castle, explains the problems that Inversion of control containers try to solve (using Castle Project)
- PocoCapsule An open source IoC and DSM framework for C++
- Domain Specific Modeling (DSM) in IoC frameworks