首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

IoC,DI和DIP什么关系

控制反转(Inversion of Control,IoC),依赖注入(Dependency Injection,DI)和依赖倒置(Dependency Inversion Principle,DIP)是学习Java编程过程中经常看到的几个概念,这几个概念有区别又有联系,名字又有些接近,很容易让人犯晕。下面对这几个概念介绍一下。

首先看一下wikipedia上对IoC的解释:

In software engineering, inversion of control (IoC) is a design principle in which custom-written portions of acomputer program receive the flow of control from a generic framework. Asoftware architecture with this design inverts control as compared totraditional procedural programming: in traditional programming, the custom codethat expresses the purpose of the program calls into reusable libraries to takecare of generic tasks, but with inversion of control, it is the framework thatcalls into the custom, or task-specific, code.

中文如下:

在软件工程中,控制反转是一个设计原则,计算机程序的自定义部分从通用框架接收控制流。相比传统的过程编程,一个使用了该设计的软件架构反转了控制。在传统编程中,自定义代码调用成可重用的库完成通用任务,但随着控制反转,框架调用自定义或任务相关的代码。

可见,所谓控制反转是和传统编程相比的。传统上程序员自己的代码控制一切,对象的创建、使用、销毁等都在代码里实现。但使用框架以后,有些控制权要交出去了,比如框架可以为你创建对象,管理对象的生命周期,甚至回调你的代码完成某些任务。这就是反转的由来。

提起IoC,就不能不提作为IoC容器的Spring,控制反转是Spring独有的吗?不是的。控制反转是框架的共性之一。比如Java Servlets也支持控制反转,因为Servlet容器管理Servlet的生命周期。马丁(Robert Martin)在文章“IoC容器和Dependency Injection模式”(http://insights.thoughtworkers.org/injection/)中指出:

几位轻量级容器的作者曾骄傲地对我说:这些容器非常有用,因为它们实现了控制反转。这样的说辞让我深感迷惑:控制反转是框架所共有的特征,如果仅仅因为使用了控制反转就认为这些轻量级容器与众不同,就好象在说我的轿车是与众不同的,因为它有四个轮子。

问题的关键在于:它们反转了哪方面的控制?我第一次接触到的控制反转针对的是用户界面的主控权。早期的用户界面是完全由应用程序来控制的,你预先设计一系列命令,例如输入姓名、输入地址等,应用程序逐条输出提示信息,并取回用户的响应。而在图形用户界面环境下,UI框架将负责执行一个主循环,你的应用程序只需为屏幕的各个区域提供事件处理函数即可。在这里,程序的主控权发生了反转:从应用程序移到了框架。对于这些新生的容器,它们反转的是如何定位插件的具体实现……而这些轻量级容器则使用了更为灵活的办法,只要插件遵循一定的规则,一个独立的组装模块就能够将插件的具体实现注射到应用程序中。因此,我想我们需要给这个模式起一个更能说明其特点的名字——”控制反转”这个名字太泛了,常常让人有些迷惑。与多位IoC 爱好者讨论之后,我们决定将这个模式叫做”依赖注入”(Dependency Injection)。

那Spring声称自己是IoC容器对不对呢?也没错,就像一个Java程序员声称自己是个程序员一样。况且,Spring容器除了依赖注入,还能管理对象生命周期,甚至监控对象状态。

到这里,依赖注入的概念也基本清楚了。依赖注入就是指被依赖的东西由它人(多部分情况是容器)负责装配。依赖注入的形式主要有三种,分别叫做构造函数注入(Constructor Injection)、设值方法注入(SetterInjection)和接口注入(Interface Injection)。这些细节这里就不展开讲了,自行网上搜索一下即可。

那控制反转、依赖注入又和DIP什么关系呢?DIP是一个设计原则,其定义是:

A. 高层模块不应该依赖于低层模块,二者都应该依赖于抽象。

B. 抽象不应该依赖于具体实现细节,而具体实现细节应该依赖于抽象。

DI的思想是通过增加一个抽象层来解耦高层模块和低层模块。如下图:

Business依赖MySQL数据库存储数据。该结构缺点耦合太紧,是更换数据库要修改Business。通过应用DI原则,结构可以变成这样:

这样Business和具体的数据实现(如MySQL)都依赖共同的抽象Persistence。Business和具体的底层数据库解耦了,更换数据库不影响Business。

总结一下:

控制反转是把一些控制(比如对象管理、方法执行等)交给它人(多为框架)来做。

依赖注入是把对象装配这类控制反转了(交给框架做)。

依赖倒置是通过引入抽象层,把高层和低层依赖关系反转了。没有依赖倒置,也可以有控制反转和依赖注入。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180110G0CJHQ00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券