控制反转( IoC)和依赖注入(DI)

tags: 容器 依赖注入 IOC DI 控制反转


引言:如果你看过一些框架的源码或者手册,像是laravel或者tp5之类的,应该会提到容器,依赖注入,控制反转等词汇。或者是某些面试官会问到这类问题。希望这篇文章能让你有所收获。

1.1、IoC(控制反转 Inversion of Control)

简述:控制反转并不是一种技术,而是一种设计思想。通过控制反转容器(以后称容器),改变了原本某些对象运行时依赖其他对象资源时需要自己进行获取(比如通过new ClassName),所造成的对象之间的强耦合(耦合的概念如果不理解,可以先去了解一下。)。

  所谓IoC,对于程序来说,就是构造了一个容器,比如在tp5中,这个容器叫Container,此容器来负责控制对象和对象间的关系。在一个对象中,如果要使用另外的对象,就必须得到它(自己new一个),这样的话一个对象A和另一个对象B之间就有了很强的联系(也就是强耦合)。这种耦合体现在如果被依赖的资源类初始化的时候(也可能是其他时候)传入的参数变化了,你要修改两个类的代码,举例说明:

  

你本来用的是php本身的session机制,现在想改成也支持redis,并在初始化的时候增加一个参数来控制。这个时候你不止需要去修改类Session类的代码,还要去修改类A的代码。部分代码如下

//原代码
class Session{
function __construct(){
//balabala
}
} class A{
protected $driver;
function __construct(){
$this->driver = new Session();
}
} //需要增加一种redis方式后修改为
class Session{
protected $driver;
function __construct(string $driver=''){
if($driver === ''){
//balabala
}else if($driver === 'redis'){//增加了一种模式
//balabala
}else{
//balabala
} }
} class A{
protected $driver;
function __construct(){
$this->driver = new Session('redis');//我想使用redis了
}
}

可以看到,不止我们修改了B的代码,还要去修改A的代码,这样如果依赖关系多起来的话,每次修改A依赖的对象,可能要处理A中很多条代码。会造成对象之间的强耦合。所以我们可以把A需要的东西,在A之前就创建出来,并通过构造函数参数传递给A。代码如下

 class A{
protected $driver;
function __construct(A $a){
//我想使用redis了
}
} $driver = new Session('redis');//我想使用redis了
$a = new A($driver)

这种方法下更改A依赖的所有对象都通过构造方法或者其他方法的形式给A,这些对象本身机制更改的时候就无需修改A的代码了。但是每次自己使用A的时候都去看看A需要些什么在前面都new一遍,感觉上很low啊,不如我们搞一个管家(容器),如果发现你需要什么,管家就给你什么。这样所依赖的类的创建都由容器来控制,也就是说控制对象创建的不再是引用它的对象,而是容器。对于某个具体的对象而言,以前是它控制其他对象,需要什么自己处理,现在是所有对象都被容器控制,所以控制反转是一种控制权的转移。

1.2、DI(依赖注入 Dependency Injection Container)

  IoC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入,或者叫依赖注入容器)来实现的。比如还是上面的例子,对象A需要操作Session,以前我们总是要在A中自己编写代码来获得一个Session对象,有了 容器这个管家我们就只需要告诉容器,A中需要一个Session对象,至于这个Session对象怎么构造,何时构造,A不需要知道。在系统运行时,容器会在适当的时候制造一个Session,通过构造方法注射到A当中,这样就完成了对各个对象之间关系的控制,而且这种关系是松耦合的。

  A需要依赖 Session才能正常运行,而这个Session是由容器注入到A中的,依赖注入的名字就这么来的。那么DI是如何实现的呢? php有一个高级特性是反射(reflection),原理这里大概说一下,

反射可以在php运行中,提取出关于类、方法、属性、参数,注释等的详细信息,并可以动态的调用方法和类等。这种动态获取的信息以及动态调用对象的方法的功能称为反射API。

反射允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,容器就是通过反射来实现注入的。

总结:

控制反转是说创建对象的控制权进行转移,由原来的资源需求方,转移到了容器,依赖注入是说本来是资源需求方依赖资源,现在资源需求方依赖于容器对资源的注入,可以看出来依赖注入和控制反转说的其实是一个事情。

顺便提一句,目前很多框架中都离不开反射功能。容器是一个典型的例子,容器在laravel和tp5中都是核心功能之一。

控制反转( IoC)和依赖注入(DI)的更多相关文章

  1. 控制反转IOC与依赖注入DI

    理解 IOC  http://www.cnblogs.com/zhangchenliang/archive/2013/01/08/2850970.html IOC 相关实例      的http:// ...

  2. 控制反转(Ioc)和依赖注入(DI)

    控制反转IOC, 全称 “Inversion of Control”.依赖注入DI, 全称 “Dependency Injection”. 面向的问题:软件开发中,为了降低模块间.类间的耦合度,提倡基 ...

  3. iOS控制反转(IoC)与依赖注入(DI)的实现

    背景 最近接触了一段时间的SpringMVC,对其控制反转(IoC)和依赖注入(DI)印象深刻,此后便一直在思考如何使用OC语言较好的实现这两个功能.Java语言自带的注解特性为IoC和DI带来了极大 ...

  4. 轻松学,浅析依赖倒置(DIP)、控制反转(IOC)和依赖注入(DI) 依赖注入和控制反转的理解,写的太好了。

    轻松学,浅析依赖倒置(DIP).控制反转(IOC)和依赖注入(DI) 2017年07月13日 22:04:39 frank909 阅读数:14269更多 所属专栏: Java 反射基础知识与实战   ...

  5. 控制反转IOC与依赖注入DI【转】

    转自:http://my.oschina.net/1pei/blog/492601 一直对控制反转.依赖注入不太明白,看到这篇文章感觉有点懂了,介绍的很详细. 1. IoC理论的背景我们都知道,在采用 ...

  6. 【转载】浅析依赖倒置(DIP)、控制反转(IOC)和依赖注入(DI)

    原文地址 http://blog.csdn.net/briblue/article/details/75093382 写这篇文章的原因是这两天在编写关于 Dagger2 主题的博文时,花了大量的精力来 ...

  7. 控制反转IOC与依赖注入DI - 理论篇

    学无止境,精益求精 十年河东十年河西,莫欺少年穷 昨天是五一小长假归来上班的第一天,身体疲劳,毫无工作热情.于是就看看新闻,喝喝茶,荒废了一天 也就在昨天,康美同事张晶童鞋让我学习下IOC的理论及实现 ...

  8. 依赖倒置(DIP)、控制反转(IOC)和依赖注入(DI)

    原文: https://blog.csdn.net/briblue/article/details/75093382 写这篇文章的原因是这两天在编写关于 Dagger2 主题的博文时,花了大量的精力来 ...

  9. 20181123_控制反转(IOC)和依赖注入(DI)

    一.   控制反转和依赖注入: 控制反转的前提, 是依赖倒置原则, 系统架构时,高层模块不应该依赖于低层模块,二者通过抽象来依赖 (依赖抽象,而不是细节) 如果要想做到控制反转(IOC), 就必须要使 ...

  10. Spring框架学习笔记(1)——控制反转IOC与依赖注入DI

    Spring框架的主要作用,就是提供了一个容器,使用该容器就可以创建并管理对象.比如说Dao类等,又或者是具有多依赖关系的类(Student类中包含有Teacher类的成员变量) Spring有两个核 ...

随机推荐

  1. strcpy函数

    不调用C/C++库函数,编写strcpy()函数. char * my_strcpy(char *strDest,const char *strSrc) { char *p=strDest; whil ...

  2. Rweibo , wordcloud

    利用Rweibo ,wordcloud做词云 #导入需要的包,不存在则下载 require(Rweibo) #必须先调用rJava不然Rwordseg 无法使用 library(rJava) requ ...

  3. Initialization error SQL*Net not properly installed

    1.错误描述 2.错误原因 由于我在64位操作系统上安装了32位PL/SQL导致出错,出现兼容性连接问题 3.解决办法 安装一个32位的Oracle客户端,Tools-Preferences-Orac ...

  4. 书籍--嵌入式C语言

    1,C语言嵌入式编程修炼 [C/C++]C语言嵌入式编程修炼·背景篇·软件架构篇·内存操作篇

  5. Python基础_函数2

    在介绍完函数的大体概念如定义.传参.作用域之后,本节主要介绍函数的几个细节部分. 一. print()函数与return的区别. 相同点:print与return都是向用户在输出界面上展示结果 不同点 ...

  6. Keras常见问题及解答

    Keras官方中文版文档 如何引用 Keras? 如何在 GPU 上运行 Keras? 如何在多 GPU 上运行 Keras 模型? "sample", "batch&q ...

  7. 【BZOJ3140】消毒(二分图匹配)

    [BZOJ3140]消毒(二分图匹配) 题面 Description 最近在生物实验室工作的小T遇到了大麻烦. 由于实验室最近升级的缘故,他的分格实验皿是一个长方体,其尺寸为abc,a.b.c 均为正 ...

  8. LightOJ1282 Leading and Trailing

    题面 给定两个数n,k 求n^k的前三位和最后三位 Input Input starts with an integer T (≤ 1000), denoting the number of test ...

  9. 改数据库编码latin1为utf8

    因为建数据库的时候没有选utf8,所以默认是latin1 在网上查了好多资料 ,试了很多种方法,都不奏效,有用的一个竟然要一列一列的改, 最后在评论里发现了这个,抱着试一试的心态竟然成功改过来了,在这 ...

  10. 通过Java WebService接口从服务端下载文件

    一. 前言 本文讲述如何通过webservice接口,从服务端下载文件.报告到客户端.适用于跨系统间的文件交互,传输文件不大的情况(控制在几百M以内).对于这种情况搭建一个FTP环境,增加了系统部署的 ...