https://segmentfault.com/a/1190000007209266
## 前言
最近在使用`ThinkPHP5`框架,看了下他的源碼,發現有很多地方也用到了依賴注入(控制反轉),覺得有必要和大家簡單聊一聊什么是依賴注入以及怎么使用它。
## 簡介
~~~coq
IoC - Inversion of Control 控制反轉
DI - Dependency Injection 依賴注入
~~~
依賴注入和控制反轉說的實際上是同一個東西,它們是一種設計模式,這種設計模式用來減少程序間的耦合
## 優勢(為什么使用)
使用依賴注入,最重要的一點好處就是有效的分離了對象和它所需要的外部資源,使得它們松散耦合,有利于功能復用,更重要的是使得程序的整個體系結構變得非常靈活。
## 概念
依賴注入和控制反轉是對同一件事情的不同描述,從某個方面講,就是它們描述的角度不同。
* 依賴注入是從應用程序的角度在描述,可以把依賴注入,即:應用程序依賴容器創建并注入它所需要的外部資源;
* 而控制反轉是從容器的角度在描述,即:容器控制應用程序,由容器反向的向應用程序注入應用程序所需要的外部資源。
## 問答
對于一個菜鳥,如果你看了上面的概念還是一頭霧水的話,那么恭喜你,你和我一樣不是天才,那么下面就讓我們借助于幾個問答來搞清楚這個概念的意思吧。
### 問題
1. 整個過程中參與者都有誰?
2. 依賴:誰依賴于誰?為什么需要依賴?
3. 注入:誰注入于誰?到底注入了什么?
4. 控制反轉:誰控制誰?控制什么?為何叫反轉(有反轉就應該有正轉了,正轉是什么呢?)
5. 依賴注入和控制反轉是同一概念嗎?
### 回答
1. 整個過程中參與者都有誰?
~~~stata
一般有三方參與者,一個是某個對象;一個是IoC/DI的容器;另一個是某個對象的外部資源。
某個對象指的就是任意的、普通的PHP對象;
IoC/DI的容器簡單點說就是指用來實現IoC/DI功能的一個框架程序;
對象的外部資源指的就是對象需要的,但是是從對象外部獲取的,都統稱資源,比如:對象需要的其它對象、或者是對象需要的文件資源等等。
~~~
2. 誰依賴于誰:
~~~stata
當然是某個對象依賴于IoC/DI的容器
~~~
3. 為什么需要依賴:
~~~stata
對象需要IoC/DI的容器來提供對象需要的外部資源
~~~
4. 誰注入于誰:
~~~stata
是IoC/DI的容器 注入 某個對象
~~~
5. 到底注入什么:
~~~undefined
就是注入某個對象所需要的外部資源
~~~
6. 誰控制誰:
~~~stata
當然是IoC/DI的容器來控制對象了
~~~
7. 控制什么:
~~~undefined
主要是控制對象實例的創建
~~~
8. 為何叫反轉:
~~~mathematica
反轉是相對于正向而言的,那么什么算是正向的呢?
考慮一下常規情況下的應用程序,如果要在A里面使用C,你會怎么做呢?當然是直接去創建C的對象,也就是說,是在A類中主動去獲取所需要的外部資源C($c = new C();),這種情況被稱為正向的。那么什么是反向呢?就是A類不再主動去獲取C,而是被動等待,等待IoC/DI的容器獲取一個C的實例,然后反向的注入到A類中。
用圖例來說明一下,先看沒有IoC/DI的時候,常規的A類使用C類的示意圖,如下圖所示:
~~~

代碼示意:
~~~php
<?php
/**
* 沒有IoC/DI的時候,常規的A類使用C類的示例
*/
/**
* Class c
*/
class c
{
public function say()
{
echo 'hello';
}
}
/**
* Class a
*/
class a
{
private $c;
public function __construct()
{
$this->c = new C(); // 實例化創建C類
}
public function sayC()
{
echo $this->c->say(); // 調用C類中的方法
}
}
$a = new a();
$a->sayC();
~~~
當有了IoC/DI的容器后,A類不再主動去創建C了,如下圖所示:

而是被動等待,等待IoC/DI的容器獲取一個C的實例,然后反向的注入到A類中,如下圖所示:

代碼示意:
~~~php
<?php
/**
* 當有了IoC/DI的容器后,a類依賴c實例注入的示例
*/
/**
* Class c
*/
class c
{
public function say()
{
echo 'hello';
}
}
/**
* Class a
*/
class a
{
private $c;
public function setC(C $c)
{
$this->c = $c; // 實例化創建C類
}
public function sayC()
{
echo $this->c->say(); // 調用C類中的方法
}
}
$c = new C();
$a = new a();
$a->setC($c);
$a->sayC();
~~~
9.什么是正轉?正轉就是按照普通的我們再類中直接創建對象實例,如 $c = new C();
10.依賴注入和控制反轉是同一概念嗎?
~~~autohotkey
根據上面的講述,我們不難出來,`依賴注入`和`控制反轉`確實是對同一件事情的不同描述,從某個方面講,就是它們描述的`角度`不同。
~~~
## 總結
其實IoC/DI對編程帶來的最大改變不是從代碼上,而是從思想上,發生了“主從換位”的變化。應用程序原本是老大,要獲取什么資源都是主動出擊,但是在IoC/DI思想中,應用程序就變成被動的了,被動的等待IoC/DI容器來創建并注入它所需要的資源了。
## 注意
我們上面說了,這是一種“設計模式”,就像“工廠模式”和“單例模式”等是一樣的,它是一種面向對象中的編程“思想”,自然它也不僅限于PHP,而是所有面向對象的語言基本都是可以適用的。
- 空白目錄1
- RBAC
- RBAC權限模型[完整]
- 你知道權限管理的RBAC模型嗎?
- rbac 一個用戶對應多個賬號_如何設計一個強大的權限系統
- Postman 快速使用(設置環境變量)
- postman的使用方法詳解!最全面的教程
- Postman常用的幾個功能
- ThinkPHP項目總結
- thinkphp5 遞歸查詢所有子代,查詢上級,并且獲取層級
- PHP原生項目之留言板
- 智慧校園
- PHP如何實現訂單的延時處理詳解
- VUE
- const {data:res} = await login(this.loginForm)
- Vue中的async和await的使用
- PHP實現消息推送(定時輪詢)
- tp5 計算兩個日期之間相差的天數
- 使用jquery的ajax方法獲取下拉列表值
- jQuery實現select下拉框選中數據觸發事件
- SetFocus 方法
- 快來了解下TP6中的超級函數app()!
- PHP socket 服務器框架 workerman
- 程序員如何才能成為獨立開發者?
- PHP 錯誤處理
- php面向對象類中的$this,static,final,const,self及雙冒號 :: 這幾個關鍵字使用方法。
- 小白教你玩轉php的閉包
- 關于TP6項目搭建的坑(多應用模式)
- ThinkPHP6.0 與5.0的差別及坑點
- axios在vue項目中的使用實例詳解
- php中的類、對象、方法是指什么
- 聊一聊PHP的依賴注入(DI) 和 控制反轉(IoC)
- 深入理解控制反轉(IoC)和依賴注入(DI)
- Private,Public,Protected
- ThinkPHP5(目錄,路徑,模式設置,命名空間)
- 在 ThinkPHP6 中使用 Workerman
- 介紹thinkphp lock鎖的使用和例子
- php中_initialize()函數與 __construct()函數的區別說明
- api接口數據-驗證-整理
- api接口數據-驗證-整理【續】
- TP6容易踩得坑【原創】
- TP6的日志怎么能記錄詳細的日志?
- 是否需要模型分層
- PHP面試題 全網最硬核面試題來了 2021年學習面試跳槽必備(一)
- MySQL單表數據量過千萬,采坑優化記錄,完美解決方案
- MySql表分區(根據時間timestamp)
- MySQL大表優化方案
- 閑言碎語
- 數據庫外鍵的使用
- 深入理解thinkphp、laravel等框架中容器概念
- vue做前端,thinkphp6做后臺,項目部署
- 簡單MVC架構的PHP留言本
- TP5里面extend和vendor的區別
- 在mysql數據庫中制作千萬級測試表
- MySQL千萬級的大表要怎么優化
- ThinkPHP關聯模型操作實例分析
- lcobucci/jwt —— 一個輕松生成jwt token的插件
- RESTful API 設計指南
- MySQL如何為表字段添加索引
- ThinkPHP6.0快速開發手冊(案例版)
- tp5 靜態方法和普通方法的區別
- 數據字典功能
- mysql中的數據庫ID主鍵的設置問題
- 基于角色的權限控制(django內置auth體系)
- RBAC系統經典五張表
- 什么是接口文檔,如何寫接口,有什么規范?
- thinkphp5.0自定義驗證器