依賴注入是個花俏的名詞,事實上是指:類的依賴經過構造器或在某些狀況下經過「setter」方法「注入」。先看一段 Laravel 控制器裏的代碼實例:php
<?php namespace App\Http\Controllers; use Illuminate\Routing\Controller; use App\Users\Repository as UserRepository; class UserController extends Controller { /** * 用戶 Repository 的實例。 */ protected $users; /** * 建立一個新的控制器實例。 * * @param UserRepository $users * @return void */ public function __construct(UserRepository $users) { $this->users = $users; } /** * 顯示指定 ID 的用戶。 * * @param int $id * @return View */ public function show($id) { $user_info = $this->users->find($id); return view('user', ['user_info' => $user_info]); } }
Laravel 經過服務容器來管理類依賴並進行依賴注入。若是使用一個接口做爲函數參數的類型提示,這個時候就須要將指定的實現綁定到接口上面:html
interface EventPusher { public function send($data); }
class RedisEventPusher implements EventPusher { public function send($data) { // } }
$this->app->bind('App\Contracts\EventPusher', 'App\Services\RedisEventPusher');
use App\Contracts\EventPusher; /** * 建立一個新的類實例。 * * @param EventPusher $pusher * @return void */ public function __construct(EventPusher $pusher) { $this->pusher = $pusher; }
這個就是所謂的面向接口編程,接口能夠理解爲一個規範、一個約束。高層模塊不直接依賴於低層模塊,它們都應該依賴於抽象(指接口)。java
使用依賴注入,最重要的一點好處就是有效的分離了對象和它所須要的外部資源,使得它們鬆散耦合,有利於功能複用,更重要的是使得程序的整個體系結構變得很是靈活。laravel
控制反轉(Inversion of Control,縮寫爲IoC),是面向對象編程中的一種設計原則。其中**最多見的方式叫作依賴注入(Dependency Injection,簡稱DI),還有一種方式叫「依賴查找」(Dependency Lookup)。經過控制反轉,對象在被建立的時候,由一個調控系統內全部對象的外界實體,將其所依賴的對象的引用傳遞給它。也能夠說,依賴被注入到對象中。程序員
<?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類中,以下圖所示:segmentfault
<?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();