聊一聊PHP的依賴注入(DI) 和 控制反轉(IoC)

前言

最近在使用ThinkPHP5框架,看了下他的源碼,發現有不少地方也用到了依賴注入(控制反轉),以爲有必要和你們簡單聊一聊什麼是依賴注入以及怎麼使用它。php

簡介

IoC - Inversion of Control  控制反轉
 DI  - Dependency Injection  依賴注入

依賴注入和控制反轉說的其實是同一個東西,它們是一種設計模式,這種設計模式用來減小程序間的耦合編程

優點(爲何使用)

使用依賴注入,最重要的一點好處就是有效的分離了對象和它所須要的外部資源,使得它們鬆散耦合,有利於功能複用,更重要的是使得程序的整個體系結構變得很是靈活。設計模式

概念

依賴注入和控制反轉是對同一件事情的不一樣描述,從某個方面講,就是它們描述的角度不一樣。框架

  • 依賴注入是從應用程序的角度在描述,能夠把依賴注入,即:應用程序依賴容器建立並注入它所須要的外部資源;this

  • 而控制反轉是從容器的角度在描述,即:容器控制應用程序,由容器反向的嚮應用程序注入應用程序所須要的外部資源。spa

問答

對於一個菜鳥,若是你看了上面的概念仍是一頭霧水的話,那麼恭喜你,你和我同樣不是天才,那麼下面就讓咱們藉助於幾個問答來搞清楚這個概念的意思吧。設計

問題

  1. 整個過程當中參與者都有誰?code

  2. 依賴:誰依賴於誰?爲何須要依賴?對象

  3. 注入:誰注入於誰?到底注入了什麼?blog

  4. 控制反轉:誰控制誰?控制什麼?爲什麼叫反轉(有反轉就應該有正轉了,正轉是什麼呢?)

  5. 依賴注入和控制反轉是同一律念嗎?

回答

  1. 整個過程當中參與者都有誰?

    通常有三方參與者,一個是某個對象;一個是IoC/DI的容器;另外一個是某個對象的外部資源。
       某個對象指的就是任意的、普通的PHP對象; 
       IoC/DI的容器簡單點說就是指用來實現IoC/DI功能的一個框架程序;
       對象的外部資源指的就是對象須要的,可是是從對象外部獲取的,都統稱資源,好比:對象須要的其它對象、或者是對象須要的文件資源等等。
  2. 誰依賴於誰:

    固然是某個對象依賴於IoC/DI的容器
  3. 爲何須要依賴:

    對象須要IoC/DI的容器來提供對象須要的外部資源
  4. 誰注入於誰:

    是IoC/DI的容器 注入 某個對象
  5. 到底注入什麼:

    就是注入某個對象所須要的外部資源
  6. 誰控制誰:

    固然是IoC/DI的容器來控制對象了
  7. 控制什麼:

    主要是控制對象實例的建立
  8. 爲什麼叫反轉:

    反轉是相對於正向而言的,那麼什麼算是正向的呢?
       考慮一下常規狀況下的應用程序,若是要在A裏面使用C,你會怎麼作呢?固然是直接去建立C的對象,也就是說,是在A類中主動去獲取所須要的外部資源C($c = new C();),這種狀況被稱爲正向的。那麼什麼是反向呢?就是A類再也不主動去獲取C,而是被動等待,等待IoC/DI的容器獲取一個C的實例,而後反向的注入到A類中。
    
       用圖例來講明一下,先看沒有IoC/DI的時候,常規的A類使用C類的示意圖,以下圖所示:

clipboard.png

代碼示意:

<?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了,以下圖所示:

clipboard.png

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

clipboard.png

代碼示意:

<?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.依賴注入和控制反轉是同一律念嗎?

根據上面的講述,咱們不難出來,`依賴注入`和`控制反轉`確實是對同一件事情的不一樣描述,從某個方面講,就是它們描述的`角度`不一樣。

總結

其實IoC/DI對編程帶來的最大改變不是從代碼上,而是從思想上,發生了「主從換位」的變化。應用程序本來是老大,要獲取什麼資源都是主動出擊,可是在IoC/DI思想中,應用程序就變成被動的了,被動的等待IoC/DI容器來建立並注入它所須要的資源了。

注意

咱們上面說了,這是一種「設計模式」,就像「工廠模式」和「單例模式」等是同樣的,它是一種面向對象中的編程「思想」,天然它也不只限於PHP,而是全部面向對象的語言基本都是能夠適用的。

相關文章
相關標籤/搜索