要想理解 PHP 依赖注入 和 控制反转 两个概念,就必须搞清楚如下的两个问题:DI —— Dependency Injection 依赖注入

IoC —— Inversion of Control 控制反转

什么是依赖注入:

没有你我就活不下去,那么,你就是我的依赖。 说白了就是:不是我自身的,却是我需要的,都是我所依赖的。一切需要外部提供的,都是需要进行依赖注入的。

依赖注入举例:class Boy {

protected $girl;

public function __construct(Girl $girl) {

$this->girl = $girl;

}

}

class Girl {

...

}

$boy = new Boy();  // Error; Boy must have girlfriend!

// 所以,必须要给他一个女朋友才行

$girl = new Girl();

$boy = new Boy($girl); // Right! So Happy!

从上述代码我们可以看到Boy强依赖Girl必须在构造时注入Girl的实例才行。

那么为什么要有依赖注入这个概念,依赖注入到底解决了什么问题?

我们将上述代码修正一下我们初学时都写过的代码:class Boy {

protected $girl;

public function __construct() {

$this->girl = new Girl();

}

}

这种方式与前面的方式有什么不同呢?

我们会发现Boy的女朋友被我们硬编码到Boy的身体里去了。。。 每次Boy重生自己想换个类型的女朋友都要把自己扒光才行。

某天Boy特别喜欢一个LoliGirl ,非常想让她做自己的女朋友。。。怎么办? 重生自己。。。扒开自己。。。把Girl扔了。。。把 LoliGirl塞进去?????class LoliGirl {

}

class Boy {

protected $girl;

public function __construct() {

//  $this->girl = new Girl();  // sorry...

$this->girl = new LoliGirl();

}

}

某天 Boy迷恋上了御姐....Boy 好烦。。。

是不是感觉不太好?每次遇到真心相待的人却要这么的折磨自己。。。

Boy说,我要变的强大一点。我不想被改来改去的!

好吧,我们让Boy强大一点:interface Girl {

// Boy need knows that I have some abilities.

}

class LoliGril implement Girl {

// I will implement Girl"s abilities.

}

class Vixen implement Girl {

// Vixen definitely is a girl, do not doubt it.

}

class Boy {

protected $girl;

public function __construct(Girl $girl) {

$this->girl = $girl;

}

}

$loliGirl = new LoliGirl();

$vixen = new Vixen();

$boy = new Boy($loliGirl);

$boy = new Boy($vixen);

Boy 很高兴,终于可以不用扒开自己就可以体验不同的人生了。。。So Happy!

依赖注入方式

1、构造器 注入<?php

class Book {

private $db_conn;

public function __construct($db_conn) {

$this->db_conn = $db_conn;

}

}

2、setter 注入<?php

class Book {

private $db;

private $file;

function setdb($db) {

$this->db = $db;

}

function setfile($file) {

$this->file = $file;

}

}

class file {

}

class db {

}

// ...

class test {

$book = new Book();

$book->setdb(new db());

$book->setfile(new file());

}

小结:

因为大多数应用程序都是由两个或者更多的类通过彼此合作来实现业务逻辑,这使得每个对象都需要获取与其合作的对象(也就是它所依赖的对象)的引用。如果这个获取过程要靠自身实现,那么将导致代码高度耦合并且难以维护和调试。

控制反转 (Inversion Of Control, IOC)

控制反转 是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做 依赖注入(Dependency Injection, DI), 还有一种叫"依赖查找"(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。<?php

class Ioc {

protected $db_conn;

public static function make_book() {

$new_book = new Book();

$new_book->set_db(self::$db_conn);

//...

//...

//其他的依赖注入

return $new_book;

}

}

此时,如果获取一个book实例,只需要执行$newone = Ioc::makebook();

以上是container的一个具体实例,最好还是不要把具体的某个依赖注入写成方法,采用registry注册,get获取比较好<?php

/**

* 控制反转类

*/

class Ioc {

/**

* @var array 注册的依赖数组

*/

protected static $registry = array();

/**

* 添加一个 resolve (匿名函数)到 registry 数组中

*

* @param string  $name    依赖标识

* @param Closure $resolve 一个匿名函数,用来创建实例

* @return void

*/

public static function register($name, Closure $resolve) {

static::$registry[$name] = $resolve;

}

/**

* 返回一个实例

*

* @param string $name 依赖的标识

* @return mixed

* @throws Exception

*/

public static function resolve($name) {

if (static::registered($name)) {

$name = static::$registry[$name];

return $name();

}

throw new Exception("Nothing registered with that name");

}

/**

* 查询某个依赖实例是否存在

*

* @param string $name

* @return bool

*/

public static function registered($name) {

return array_key_exists($name, static::$registry);

}

}

现在就可以通过如下方式来注册和注入一个<?php

Ioc::register("book", function () {

$book = new Book();

$book->setdb("db");

$book->setfile("file");

return $book;

});

// 注入依赖

$book = Ioc::resolve("book");

问题汇总

1、参与者都有谁?

答:一般有三方参与者,一个是某个对象;一个是IoC/DI的容器;另一个是某个对象的外部资源。又要名词解释一下,某个对象指的就是任意的、普通的Java对象; IoC/DI的容器简单点说就是指用来实现IoC/DI功能的一个框架程序;对象的外部资源指的就是对象需要的,但是是从对象外部获取的,都统称资源,比如:对象需要的其它对象、或者是对象需要的文件资源等等。

2、依赖:谁依赖于谁?为什么会有依赖?

答:某个对象依赖于IoC/DI的容器。依赖是不可避免的,在一个项目中,各个类之间有各种各样的关系,不可能全部完全独立,这就形成了依赖。传统的开发是使用其他类时直接调用,这会形成强耦合,这是要避免的。依赖注入借用容器转移了被依赖对象实现解耦。

3、注入:谁注入于谁?到底注入什么?

答:通过容器向对象注入其所需要的外部资源

4、控制反转:谁控制谁?控制什么?为什么叫反转?

答:IoC/DI的容器控制对象,主要是控制对象实例的创建。反转是相对于正向而言的,那么什么算是正向的呢?考虑一下常规情况下的应用程序,如果要在A里面使用C,你会怎么做呢?当然是直接去创建C的对象,也就是说,是在A类中主动去获取所需要的外部资源C,这种情况被称为正向的。那么什么是反向呢?就是A类不再主动去获取C,而是被动等待,等待IoC/DI的容器获取一个C的实例,然后反向的注入到A类中。

5、依赖注入和控制反转是同一概念吗?

答:从上面可以看出:依赖注入是从应用程序的角度在描述,可以把依赖注入描述完整点:应用程序依赖容器创建并注入它所需要的外部资源;而控制反转是从容器的角度在描述,描述完整点:容器控制应用程序,由容器反向的向应用程序注入应用程序所需要的外部资源。

参考:

Laravel 中的 依赖注入 与 控制反转

python ioc di_PHP的依赖注入(DI) 和 控制反转(IoC)相关推荐

  1. PHP依赖注入(DI)和控制反转(IoC)详解

    这篇文章主要介绍了PHP依赖注入(DI)和控制反转(IoC)的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 首先依赖注入和控制反转说的是同一个东西,是一种设计模式,这种设计模式用来减少程 ...

  2. 代码的演化-DI(理解依赖注入di,控制反转ioc)

    控制反转(Inversion of Control IoC)在java中,Spring就是一个很好的应用.用于解除使用者和生产者的耦合. 一般的代码中.使用者即是生产者,使用者在调用它需要的对象的时候 ...

  3. ioc控制反转_深入理解依赖注入(DI)和控制反转(IOC)

    转载本文务必须注明出处.微信号(Yemeir_com).以及添加原文链接. 为什么要使用依赖注入 使用依赖注入(DI)可以使控制者与抽象实现者松耦合,便于单元测试.通过控制反转(IOC)的设计原理来减 ...

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

    为什么80%的码农都做不了架构师?>>>    1. IoC理论的背景 我们都知道,在采用面向对象方法设计的软件系统中,它的底层实现都是由N个对象组成的,所有的对象通过彼此的合作,最 ...

  5. 控制反转IOC、依赖注入DI的详细说明与举例

    文章目录 引入 IOC介绍 IOC的实现 通过构造函数注入依赖 通过 setter 设值方法注入依赖 依赖注入容器 IOC优缺点 优点 缺点 阅读时忽略语言差异,参考了很多其他博主内容,参考博文在最后 ...

  6. Spring学习3—控制反转(IOC)Spring依赖注入(DI)和控制反转(IOC)

    一.思想理解    Spring 能有效地组织J2EE应用各层的对象.不管是控制层的Action对象,还是业务层的Service对象,还是持久层的DAO对象,都可在Spring的 管理下有机地协调.运 ...

  7. 依赖倒置(DIP),控制反转(IoC)与依赖注入(DI)

    DIP,IoC与DI概念解析 依赖倒置 DIP(Dependency Inversion Principle) DIP的两大原则: 1.高层模块不应该依赖于低层模块,二者都应该依赖于抽象. 2.抽象不 ...

  8. [教程]控制反转(IoC)与依赖注入(DI)

    来源: http://zhangjunhd.blog.51cto.com/113473/126530/ 挺简单的,说的也很清楚 ※IoC/DI 依赖Java的反射机制 1.控制反转(Inversion ...

  9. 控制反转(IoC)与依赖注入(DI)详解

    文章目录 什么是控制反转(IoC) 控制反转(IoC)有什么作用 控制反转(IoC)是怎么分类的 依赖注入 接口注入 Setter方法注入 构造器注入 依赖查找 上下文依赖查找(Contextuali ...

最新文章

  1. 前端每日实战:45# 视频演示如何用纯 CSS 创作一个菱形 loader 动画
  2. 2020应届生:今年秋招也太太太太太难了吧!
  3. python类的静态属性和静态方法_详解Python中的静态方法与类成员方法
  4. 安卓setclicklistener函数没有_金主脚本按键精灵安卓按键初体验—乱斗西游2自动签到...
  5. http://jsbeautifier.org/
  6. 6993: Dominoes(纯bfs)
  7. 深入理解Spark 2.1 Core (十):Shuffle Map 端的原理与源码分析
  8. qstring截取一段字符串_笔记 | 自学Python 05:数据类型之字符串
  9. 送花(洛谷 2073)
  10. Angualr 输入文本框监听enter回车键和esc键方法使用(附常用的键盘事件对应的键码)
  11. matlab做三次拉格朗日插值多项式_买菜必用的MATLAB拉格朗日插值函符号解输出
  12. 【实战】在qgis上查看街景照片( go2streetview谷歌街景、go2mapillary)
  13. 记升级springboot1.X 到springboot2.3.5踩的坑
  14. 国内某厂商摄像头敏感信息泄露漏洞事件分析
  15. vue3.0+ts+element-plus多页签应用模板:element-plus按需引入与动态换肤
  16. Pr速成3小时学会视频剪辑[副业学习会]
  17. hd printer lexmark / dazifuyin / dayin / fuyin
  18. springboot 自定义日期出入参
  19. 【25】核心易中期刊推荐——智能控制机器人
  20. python 高级技巧

热门文章

  1. leetcode 402. Remove K Digits | 402. 移掉 K 位数字(单调栈)
  2. 左神算法:生成窗口最大值数组(Java版)
  3. 高并发负载均衡(三):LVS的DR模型试验搭建
  4. Spring5参考指南:JSR 330标准注解
  5. winform中openfiledialog过滤压缩文件格式_什么是最佳图像格式?不同的文件格式及其特点...
  6. Insyde uefi 隐藏设置_安卓福利,手机桌面图标隐藏,找应用按字母轻松搞定!
  7. Effective Java之请不要在新代码中使用原生态类型(二十三)
  8. 可迭代协议与for-of循环
  9. 【详解】CSS阴影用法——Web前端系列学习笔记
  10. 解题报告——蓝桥 试题 基础练习 矩阵乘法——27行代码AC