最近看設計模式以及laravel代碼,對於控制反轉以及依賴注入這些概念很是困惑,因而找了一些資料,如下是對於控制反轉的一下理解。php
控制反轉(Inversion of Control,縮寫爲IoC),是面向對象編程中的一種設計原則,能夠用來減低計算機代碼之間的耦合度。它把傳統上由程序代碼直接操控的對象的調用權交給容器,經過容器來實現對象組件的裝配和管理。所謂的「控制反轉」概念就是對組件對象控制權的轉移,從程序代碼自己轉移到了外部容器。其中最多見的方式叫作依賴注入(Dependency Injection,簡稱DI),還有一種方式叫「依賴查找」(Dependency Lookup)。經過控制反轉,對象在被建立的時候,由一個調控系統內全部對象的外界實體,將其所依賴的對象的引用傳遞給它。也能夠說,依賴被注入到對象中。
正如概念中描述的,那麼控制反轉具體指哪些 控制 被 反轉 了呢,其實我理解的控制反轉是指程序所控制的對象的控制權交給了容器,而這個容器就是實現各個模塊解耦合的關鍵。IoC只是一種設計思想,主要實現有:laravel
咱們着重說一下依賴注入。編程
在軟件工程中,依賴注入是種實現控制反轉用於解決依賴性設計模式。一個依賴關係指的是可被利用的一種對象(即服務提供端) 。依賴注入是將所依賴的傳遞給將使用的從屬對象(即客戶端)。該服務是將會變成客戶端的狀態的一部分。 傳遞服務給客戶端,而非容許客戶端來創建或尋找服務,是本設計模式的基本要求。
以上是wikipedia上對於依賴注入的理解,下面將用實際的例子詳細講解。設計模式
加入咱們設計一個通用的用戶登陸基類,能夠支持多個平臺的用戶登陸
那麼最糟糕的寫法是,框架
/** * A類用戶登陸 **/ class User_A_Login { public function checkALogin(){ }; } /** * B類用戶登陸 **/ class User_B_Login { public function checkBLogin(){ }; } /** * 登陸基類 **/ class User_Login { public function checkLogin($userType) { if($userType = 'A'){ $this->objAUser = new User_A_Login(); $this->objAUser->checkALogin(); }elseif($userType = 'B'){ $this->objBUser = new User_B_Login(); $this->objBUser->checkBLogin(); } } }
上面的 User_Login 這個類就直接依賴於類 User_A_Login 和 User_B_Login ,若是咱們使用下面這種方式寫函數
interface User_Login_Interface { public function checkLogin(); } /** * A類用戶登陸 **/ class User_A_Login implements User_Login_Interface { public function checkLogin(){ }; } /** * B類用戶登陸 **/ class User_B_Login implements User_Login_Interface { public function checkLogin(){ }; } /** * 登陸基類 **/ class User_Login { public $userLogin; public function setUser(User_Login_Interface $user){ $this->userLogin = $user; } public function checkLogin() { $this->userLogin->checkLogin(); } }
若是按照這種方式進行構建代碼,咱們將依賴項User_B_Login或者User_A_Login經過函數 setUser( ) 注入到類中,調用方式:this
$userLogin = new User_Login(); $userLogin->setUser(new User_A_Login); $userLogin->checkLogin();
調用方能夠控制使用那個登陸類型,這就完成了對於不一樣登陸系統的依賴注入。若是你引入了一個新的用戶c,只需寫一個c的登陸類:設計
/** * C類用戶登陸 **/ class User_C_Login implements User_Login_Interface { public function checkLogin(){ }; }
就能夠經過:code
$userLogin = new User_Login(); $userLogin->setUser(new User_C_Login); $userLogin->checkLogin();
進行登陸驗證了。在實際代碼中因爲基類很是複雜須要對登陸作一系列處理,因此每次添加登陸用戶不該該去修改基類。對於一下框架例如laravel的框架是不能修改的,應該就是經過這種方式實現的調用方的自定義。對象