聲明:本文並不是博主原創,而是來自對《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); }
而後,將接口的實現注入到Authenticator
:code
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
如今依賴兩個高階抽象:UserProviderInterface
和HasherInterface
。咱們就能自由的將任何針對接口的實現注入到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
自己進行修改。傳統的依賴痛過「倒置」就能事代碼變得很是靈活,易於改變!開發