Laravel深刻學習12 - 依賴倒置原則

聲明:本文並不是博主原創,而是來自對《Laravel 4 From Apprentice to Artisan》閱讀的翻譯和理解,固然也不是原汁原味的翻譯,能保證90%的原汁性,另外由於是理解翻譯,確定會有錯誤的地方,歡迎指正。redis

歡迎轉載,轉載請註明出處,謝謝!數據庫

依賴反轉原則

介紹

咱們來到了SOLID設計原則的最終的目標遠景!它就是依賴反轉原則,它是指高階代碼不能依賴低階代碼。相應的,高階代碼應該依賴一個抽象層,它是在高階代碼和低階代碼之間的「中間人」角色。另外一方面,該原則指代抽象層不依賴具體實現,而是細節依賴抽象。若是這個讀起來很晦澀,別擔憂。咱們下面會對這兩個方面具體的闡述本原則。ide

依賴反轉原則 本原則是指高階代碼不依賴低階代碼,抽象不依賴具體細節。this

實探

若是你已經讀過本書以前的章節,就應該對依賴反轉有一個很好的理解。咱們經過下面例子來解釋:翻譯

class Authenticator {

    public function __construct(DatabaseConnection $db)
    {
        $this->db = $db;
    }

    public function findUser($id)
    {
        return $this->db->exec('select * from users where id = ?', array($id));
    }

    public function authenticate($credentials)
    {
        // Authenticate the user...
    }

}

能夠猜到,Authenticator類是負責查找並驗證用戶的。咱們來檢驗下類的構造器。能夠看到咱們有個連接數據庫的實例DatabaseConnection。因此咱們將驗證器和數據庫緊密的接合在一塊兒了,這意味着用戶對象必須創建在關係型數據庫查詢之上。此外,咱們的高階代碼(Authenticator類)直接依賴了低階代碼(DatabaseConnection類)。 首先,咱們解釋下「高階」和「低階」代碼。低階代碼實現像這種磁盤文件訪問,數據庫接入等。高階代碼在低階代碼之上實現邏輯功能的封裝,但不能將他們耦合進來。或者,高階代碼依賴創建在低階代碼之上的抽象層,如接口。不只如此,低階代碼_也_依賴於抽象層。咱們來實現一個能夠在Authenticator類中使用的接口:設計

interface UserProviderInterface {
    public function find($id);
    public function findByUsername($username);
}

而後,將接口的實現注入到Authenticatorcode

class Authenticator {

    public function __construct(UserProviderInterface $users,
    HasherInterface $hash)
    {
        $this->hash = $hash;
        $this->users = $users;
    }

    public function findUser($id)
    {
        return $this->users->find($id);
    }

    public function authenticate($credentials)
    {
        $user = $this->users->findByUsername($credentials['username']);

        return $this->hash->make($credentials['password']) == $user->password;
    }

}

這些改變以後,咱們的Authenticator如今依賴兩個高階抽象:UserProviderInterfaceHasherInterface。咱們就能自由的將任何針對接口的實現注入到Authenticator中了。好比,若是咱們用戶存儲在Reids中,能夠實現針對UserProvider實現一個RedisUserProvider類。Authenticator如今不在直接依賴低階的存儲操做了。 此外,自從它實現接口自己後,咱們的低階代碼如今也是依賴高階的UserProviderInterface抽象:對象

class RedisUserProvider implements UserProviderInterface {

    public function __construct(RedisConnection $redis)
    {
        $this->redis = $redis;
    }

    public function find($id)
    {
        $this->redis->get('users:'.$id);
    }

    public function findByUsername($username)
    {
        $id = $this->redis->get('user:id:'.$username);

        return $this->find($id);
    }

}

反轉思想 不少開發人員在應用中使用_反轉_原則。代替這種高階直接耦合低階代碼的「自上而下」的方式,本原則指高階、低階代碼「同時」依賴一個高階抽象層。接口

在咱們將Authenticator的依賴「倒置」前,他是沒法在其餘數據存儲系統中使用的。在改變存儲系統的狀況下,必須對Authenticator進行修改,違背了開放封閉原則。咱們已經知道,幾種原則之間是相互貫穿的。 在將Authenticator強制實如今存儲層之上的抽象層,咱們能夠根據UserProviderInterface接口約定切換成任意其餘存儲系統,而無需對Authenticator自己進行修改。傳統的依賴痛過「倒置」就能事代碼變得很是靈活,易於改變!開發

相關文章
相關標籤/搜索