根据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不仅仅是对象或程序员与框架之间控制的反转。


当前回答

与其直接对比DI和IoC,不如从头开始:每个重要的应用程序都依赖于其他代码段。

所以我写一个类,MyClass,我需要调用一个方法YourService…我需要以某种方式获取YourService的一个实例。最简单、最直接的方法是自己实例化它。

YourService service = new YourServiceImpl();

直接实例化是获取依赖项的传统(过程性)方法。但它有许多缺点,包括MyClass与YourServiceImpl的紧密耦合,这使得我的代码难以更改和测试。MyClass并不关心YourService的实现是什么样子,所以MyClass不想负责实例化它。

我更喜欢把这个责任从MyClass转移到MyClass之外的东西。最简单的方法是将实例化调用(new YourServiceImpl();)移动到其他类中。我可以将这个类命名为Locator,或者Factory,或者其他任何名称;但重点是MyClass不再对YourServiceImpl负责。我颠倒了依赖关系。太好了。

问题是,MyClass仍然负责对定位器/工厂/任何东西的调用。因为我反转依赖关系所做的全部工作就是插入一个中间人,所以现在我耦合到中间人(即使我没有耦合到中间人给我的具体对象)。

我并不真正关心依赖项来自何处,因此我宁愿不负责进行检索依赖项的调用。仅仅反转依赖本身是不够的。我想反转整个过程的控制。

What I need is a totally separate piece of code that MyClass plugs into (call it a framework). Then the only responsibility I'm left with is to declare my dependency on YourService. The framework can take care of figuring out where and when and how to get an instance, and just give MyClass what it needs. And the best part is that MyClass doesn't need to know about the framework. The framework can be in control of this dependency wiring process. Now I've inverted control (on top of inverting dependencies).

将MyClass连接到框架中有不同的方法。注入就是这样一种机制,通过这种机制,我只需声明一个我期望框架提供的字段或参数,通常是在它实例化MyClass时。

我认为所有这些概念之间的关系层次比这个线程中的其他图表所显示的要稍微复杂一些;但其基本思想是,这是一种等级关系。我觉得这和野外的DIP是同步的。

其他回答

1) DI是Child->obj依赖于parent-obj。动词“视情况而定”很重要。 2) IOC是Child->obj在一个平台下执行。平台可以是学校,大学,舞蹈班。这里的perform是在任何平台提供者下具有不同含义的活动。

实际的例子: `

//DI
child.getSchool();
//IOC
child.perform()// is a stub implemented by dance-school
child.flourish()// is a stub implemented by dance-school/school/

`

-AB

IOC(控制反转):将获取对象实例的控制权交给容器称为控制反转。这意味着你不用new操作符来创建对象,而是让容器来为你创建对象。

DI(依赖注入):将所需的参数(属性)从XML传递到对象(在POJO类中)称为依赖注入。

控制反转是一种设计范式,其目标是为应用程序的目标组件提供更多的控制,即完成工作的组件。 依赖注入是一种模式,用于创建其他对象所依赖的对象实例,而在编译时不知道将使用哪个类来提供该功能。

实现控制反转有几种基本技术。这些都是:

使用工厂模式 使用服务定位器模式 使用任何给定类型的依赖注入: 1).构造函数注入 2). setter注入 3).接口注入

IoC -控制反转是一个通用术语,与语言无关,它实际上不是创建对象,而是描述如何创建时尚对象。

依赖注入是一个具体的术语,我们通过使用不同的注入技术,即Setter注入、构造函数注入或接口注入,在运行时提供对象的依赖关系。

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")
    }
}