控制反轉(Inversion of Control,縮寫為IoC)和依賴注入(Dependency Injection)在當今軟體工程中佔有舉足輕重的地位,兩者之間有著密不可分的聯絡。
接下來將深入淺出,舉例說明什麼是控制反轉,什麼是依賴注入,以及它們之間的關係。
什麼是依賴注入?依賴注入就是引數傳遞
上面的定義你也許會感到驚訝,就這?是的,就是這麼簡單。依賴注入是在一個類中以引數傳遞的形式引入另外的類,它本身是引數傳遞的一種形式。但是,反過來就不成立,引數傳遞不一定是依賴注入,可能是普通的引數,而非某個類。可能這麼定義還不夠清晰,下面的程式碼將幫助你理解,
class IocTest{ protected $logger; public function __constructor(DbLogger $logger){ $this->logger = $logger; } public function hello(){ $this->logger->hello(); }}
這裡的IocTest類,透過依賴注入的方式引用了DbLogger類,這裡假設DbLogger是將日誌寫入資料庫。程式碼使用PHP編寫,本身比較簡單,可以使用任何面向物件的程式語言改寫。
什麼是控制反轉?高等級的程式碼不能依賴低等級的程式碼;抽象介面不能依賴具體實現;上面是控制反轉的定義,同樣比大多數文章描述的簡單,定義本該這麼簡潔。所謂高等級的程式碼,可以理解為抽象類、介面、裝飾類等等;所謂低等級的程式碼,可以理解為抽象類的具體實現,定義具體功能的類。這麼說可能還是不夠直觀,還是舉例說明,
IoC&DI
這張圖比較主觀的說明了什麼是控制反轉和依賴注入,同時也很好的說明了它們之間的關係。如果IocTest類依賴具體的類DbLogger,程式碼完全失去了靈活性,當我們需要將日誌輸出到檔案,需要建立一個新的IocTest類,將依賴的DbLogger改成FileLogger,
class IocTest{ protected $logger; public function __constructor(FileLogger $logger){ $this->logger = $logger; } public function hello(){ $this->logger->hello(); }}
要解決這個問題,需要對DbLogger和FileLogger進行抽象,IocTest類依賴抽象類LoggerInterface,這樣就實現了程式碼的解耦,IocTest不需要強依賴於具體類,增加了可擴充套件性。
總結控制反轉解決程式碼的強耦合,增加了程式碼的可擴充套件性,這也就是為什麼當今流行的框架Spring Boot和Laravel底層都是採用IoC;控制反轉是為了實現更靈活的依賴注入,而非消滅依賴注入;當解決過度依賴,對具體類進行抽象的時候,便產生了Ioc,之後依賴注入的是抽象類。
最新評論