根据Martin Fowler所写的论文,控制反转是程序控制流反转的原理:由外部源(框架、服务、其他组件)控制程序流,而不是由程序员控制程序流。就像我们把一个东西插入另一个东西。他提到了一个关于EJB 2.0的例子:
例如,会话Bean接口
定义ejbRemove, ejbPassivate
(存储到二级存储),以及
ejbActivate(从被动恢复
状态)。你不能控制时间
这些方法被调用,只是什么
他们做的事。集装箱召唤我们,我们
别这么说。
这就导致了framework和library的区别:
控制反转是一个关键的部分
框架与框架的区别是什么
图书馆。图书馆本质上是一个
一组你可以调用的函数,
这些日子通常组织成
类。每次调用都要做一些工作
将控制权返回给客户端。
我认为,DI是IOC的观点,意味着对象的依赖关系是倒置的:而不是它控制自己的依赖关系、生命周期……其他东西可以帮你。但是,正如你告诉我的DI by hands, DI不一定是IOC。我们仍然可以有DI,没有IOC。
然而,在本文中(来自pococapsule, C/ c++的另一个IOC框架),它指出,由于IOC和DI, IOC容器和DI框架要比J2EE优越得多,因为J2EE将框架代码混合到组件中,因此它不是普通的旧Java/ c++对象(POJO/POCO)。
依赖注入模式以外的控制反转容器(存档链接)
附加阅读,了解旧的基于组件的开发框架的问题,这导致了上面的第二篇论文:为什么和什么反转控制(档案链接)
我的问题:IOC和DI到底是什么?我很困惑。基于pococapsule, IOC不仅仅是对象或程序员与框架之间控制的反转。
让我们从SOLID的D开始,看看Scott Millett的书《Professional ASP. IoC》中的DI和IoC。NET设计模式":
Dependency Inversion Principle (DIP)
The DIP is all about isolating your classes from concrete
implementations and having them depend on abstract classes or
interfaces. It promotes the mantra of coding to an interface rather
than an implementation, which increases flexibility within a system by
ensuring you are not tightly coupled to one implementation.
Dependency Injection (DI) and Inversion of Control (IoC)
Closely linked to the DIP are the DI principle and the IoC principle. DI is the act of supplying a low level or dependent class via a
constructor, method, or property. Used in conjunction with DI, these
dependent classes can be inverted to interfaces or abstract classes
that will lead to loosely coupled systems that are highly testable and
easy to change.
In IoC, a system’s flow of control is inverted
compared to procedural programming. An example of this is an IoC
container, whose purpose is to inject services into client code
without having the client code specifying the concrete implementation.
The control in this instance that is being inverted is the act of the
client obtaining the service.
米勒特,C(2010)。专业的ASP。NET设计模式。威利出版社,7-8。
DI和IOC是两种主要侧重于提供组件之间的松耦合的设计模式,或者简单地说,这是一种解耦对象之间传统依赖关系的方法,这样对象之间就不会紧密相连。
通过下面的例子,我试图解释这两个概念。
以前我们是这样写代码的
Public MyClass{
DependentClass dependentObject
/*
At somewhere in our code we need to instantiate
the object with new operator inorder to use it or perform some method.
*/
dependentObject= new DependentClass();
dependentObject.someMethod();
}
使用Dependency注入,依赖注入器将负责对象的实例化
Public MyClass{
/* Dependency injector will instantiate object*/
DependentClass dependentObject
/*
At somewhere in our code we perform some method.
The process of instantiation will be handled by the dependency injector
*/
dependentObject.someMethod();
}
上述将控件交给其他容器(例如容器)进行实例化和注入的过程可以称为控制反转,IOC容器为我们注入依赖项的过程可以称为依赖项注入。
IOC是程序控制流颠倒过来的原则:不是由程序员控制程序的流,而是由程序通过减少程序员的开销来控制流程。程序用来注入依赖的过程称为DI
这两个概念一起工作为我们提供了一种编写更加灵活、可重用和封装的代码的方法,这使得它们在设计面向对象的解决方案时成为重要的概念。
也推荐阅读。
什么是依赖注入?
你也可以在这里查看我的一个类似的答案
控制反转和依赖注入的区别
DIP vs DI vs IoC
[依赖倒置原则(DIP)]是SOLID[About]的一部分,它要求你使用抽象而不是实现
依赖注入(DI) -使用聚合而不是组合[关于]在这种情况下,外部对象负责内部的逻辑。哪一种方法使您拥有更动态和更可测试的方法
class A {
B b
//injecting B via constructor
init(b: B) {
self.b = b
}
}
控制反转(IoC)是一个非常高级的定义,它更多地是关于控制流的。最好的例子是控制反转(IoC)容器或框架。例如,GUI是一个框架,你没有一个控制,你能做的一切只是实现框架的接口,当一些动作发生在框架中时,它会被调用。这样,控制权就从应用程序转移到了正在使用的框架中
DIP +
class A {
IB ib
init(ib: IB) {
self.ib = ib
}
}
你也可以使用:
(工厂方法)
(服务定位器)
[ioc容器(框架)]
更复杂的例子
多层/模块结构中的依赖规则
伪代码:
interface InterfaceInputPort {
func input()
}
interface InterfaceOutputPort {
func output()
}
class A: InterfaceOutputPort {
let inputPort = B(outputPort: self)
func output() {
print("output")
}
}
class B: InterfaceInputPort {
let outputPort: InterfaceOutputPort
init(outputPort: InterfaceOutputPort) {
self.outputPort = outputPort
}
func input() {
print("input")
}
}
控制反转(IoC)模式是关于提供任何类型的回调,它“实现”和/或控制反应,而不是我们自己直接操作(换句话说,反转和/或重定向控制到外部处理程序/控制器)。
例如,不是让应用程序调用库(也称为工具包)提供的实现,而是库和/或框架调用应用程序提供的实现。
依赖注入(DI)模式是IoC模式的一个更具体的版本,其中实现通过构造函数/设置器/服务查找传递到对象中,对象将“依赖”这些以正确地行为。
每个DI实现都可以被认为是IoC,但不应该称之为IoC,因为实现依赖注入比实现回调更难(不要使用通用术语“IoC”来降低产品的价值)。
例如,不使用DI的IoC将是Template模式,因为实现只能通过子类化来更改。
依赖注入框架被设计为使用依赖注入,并且可以定义接口(或Java中的注释)以方便在实现中传递。
IoC容器是可以在编程语言之外工作的依赖注入框架。在某些情况下,您可以在元数据文件(例如XML)中配置要使用的实现,这是侵入性较小的。有一些可以做IoC,这通常是不可能的,比如在切入点注入实现。
参见Martin Fowler的文章。