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

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
简介: 控制反转( IoC)和依赖注入(DI)tags: 容器 依赖注入 IOC DI 控制反转引言:如果你看过一些框架的源码或者手册,像是laravel或者tp5之类的,应该会提到容器,依赖注入,控制反转等词汇。

控制反转( 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中都是核心功能之一。

希望大家多评论交流,互相学习
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
6月前
|
XML Java 数据格式
从六个方面读懂IoC(控制反转)和DI(依赖注入)
在一开始学习 Spring 的时候,我们就接触 IoC 了,作为 Spring 第一个最核心的概念,我们在解读它源码之前一定需要对其有深入的认识,对于初学Spring的人来说,总觉得IOC是模糊不清的,是很难理解的,今天和大家分享网上的一些技术大牛们对Spring框架的IOC的理解以及谈谈我对Spring IOC的理解。
194 2
|
3月前
|
设计模式 Java 容器
控制反转 (IoC)
【8月更文挑战第24天】
39 0
|
6月前
|
容器
02_IOC控制反转 DI依赖注入
02_IOC控制反转 DI依赖注入
46 0
|
XML Java 测试技术
springIOC(控制反转)和DI(依赖注入)
springIOC(控制反转)和DI(依赖注入)
70 0
|
6月前
|
容器
IOC 控制反转和DI依赖注入
IOC 控制反转和DI依赖注入
|
Java Maven
SpringFrame-ioc 依赖注入
SpringFrame-ioc 依赖注入
|
JavaScript uml 容器
Ioc——控制反转
Ioc——控制反转
205 0
Ioc——控制反转
|
自动驾驶 小程序 Java
什么是控制反转(IOC)?什么是依赖注入?
什么是控制反转(IOC)?什么是依赖注入?
什么是控制反转(IOC)?什么是依赖注入?
IOC控制反转 + DI依赖注入
一种思想,两种实现方式 IOC (Inversion of Control):控制反转,是一种概念和思想,指由Spring容器完成对象创建和依赖注入 核心业务:(a)对象的创建 (b)依赖的注入 2种实现方式 基于xml实现IOC 基于注解实现IOC 基于xml的IOC在前3篇Spring博客中简单探讨过了,后面将探讨基于注解的IOC
|
Java Spring
Spring - IOC(控制反转) & DI(依赖注入)
Spring - IOC(控制反转) & DI(依赖注入)
136 0
Spring - IOC(控制反转) & DI(依赖注入)