依赖注入

维基百科,自由的百科全书
跳转至: 导航搜索

軟件工程中,依賴注入是種實現控制反轉用於解決依賴性設計模式。一個依賴關係指的是可被利用的一種對象(即服務提供端) 。依賴注入是將所依賴的傳遞給將使用的從屬對象(即客戶端)。該服務是將會變成客戶端的狀態的一部分。 傳遞服務給客戶端,而非允許客戶端來建立或尋找服務,是本設計模式的基本要求。

範例[编辑]

假設你今天正使用 PHP 建立一個大型專案,這個時候會有許多的類別,並且互相依賴著,下面是一個登入系統的依賴注入範例。

首先這個登入系統分成三個部分,一個是驗證,一個是處理工作階段,另一個是驅動這兩個的「主程式」。

傳統案例[编辑]

這是一個沒有使用依賴注入的傳統案例。

主要程式[编辑]

這一個程式用來進行實作用途,一旦要求登入,這個主程式就會建立「驗證」和「工作階段」兩個類別用以實作。

class Application
{
    function __construct($db, $dbUsername, $dbPassword)
    {
        $this->auth    = new Auth($db, $dbUsername, $dbPassword);
        $this->session = new Session();
    }
    
    function login($username, $password)
    {
        /** 詢問 Auth 驗證帳號密碼,如果正確則呼叫 Session 存入使用者帳號 */
        if($this->auth->validate($username, $password))
            $this->session->set('username', $username);
    }
}

驗證[编辑]

在這裡和資料庫連線,並且檢查帳號密碼是否正確。

class Auth
{
    /** 一但 Auth 被建立,則會建立 MySQL 資料庫 */
    function __construct($db, $dbUsername, $dbPassword)
    {
        $this->database = new MySQL($db, $dbUsername, $dbPassword);
    }
    
    /** 用來驗證帳號密碼是否和資料庫內的相符 */
    function validate($username, $password)
    {
        return $this->database->where('username', $username)
                              ->where('password', $password);
    }
}

工作階段[编辑]

這個類別用來將使用者登入的階段保存起來,讓伺服器清楚地知道使用者登入了。

class Session
{
    function set($name, $value)
    {
        $_SESSION[$name] = $value;
    }
}

問題[编辑]

當我們實作「主程式」的時候,並不知道主程式呼叫了什麼(除非我們查看主程式的原始碼),

像下面這樣實作就會意識到這個問題。

$application = new Application('localhost', 'root', '');

/** login() 依賴了什麼類別? */
/** 在這途中又實作了什麼類別? */
$application->login('admin', 'admin');

使用依賴注入的案例[编辑]

依賴注入的觀念就是將所有東西先在「外面」準備好,然後再帶入「內部」的程式中,如此一來你就能夠在檢視程式碼的時候,一目了然地知道這個程式依賴著哪些類別。

主要程式[编辑]

現在讓我們從頭來過,這次「主程式」不自己實作類別,而是接受在外部建立好的類別。

class Application
{
    function __construct(Auth $auth, Session $session)
    {
        $this->auth    = $auth;
        $this->session = $session;
    }
    
    // ... 程式 ...
}

然後實作這一個登入系統像這樣:

$auth        = new Auth('localhost', 'root', '');
$session     = new Session();
$application = new Application($auth, $session);

/** 嗯.. 所以我用了 Auth 跟 Session 兩個類別 */
$application->login('admin', 'admin');

這即是一個簡易的依賴注入案例,但還有一些依賴的問題尚未解決,而這又牽扯到了依賴注入容器(DI Container)。