本文內容部分摘自 Wikipedia - Inversion of Control .
IoC (控制反轉),是物件導向程式設計中的一種設計原則,可以用來減低計算機程式碼之間的耦合度。
實現「控制反轉」,有兩種方式:
- Dependency Injection (DI) - 依賴注入
- Dependency Lookup - 依賴查詢
兩者的區別在於,前者是被動的接收物件,在類例項建立過程中即建立了依賴的物件,透過型別或名稱來判斷將不同的物件注入到不同的屬性中,而後者是主動索取相應型別的物件,獲得依賴物件的時間也可以在程式碼中自由控制。
哪些方面的「控制」被「反轉」了?
依賴物件的「獲得」被反轉了。
技能描述
Class A 中用到了 Class B 的物件 b,一般情況下,需要在 A 的程式碼中顯式的 new 一個 B 的物件。採用依賴注入技術之後,A 的程式碼只需要定義一個私有的B物件,不需要直接 new 來獲得這個物件,而是透過相關的 容器控制程式
來將 B 物件在外部 new 出來並注入到 A 類裡的引用中。而具體獲取的方法、物件被獲取時的狀態由 容器
來指定。
假設我有一個 iPhone,我的 iPhone 依賴充電器才能充電。
class iPhone
{
// 電量
private $power;
// 充電
public function charge()
{
}
}
我還有個蘋果原裝充電器:
class AppleCharger
{
public function charge()
{
return 100;
}
}
在以前,iPhone 內部「控制」著只能用哪一款充電器:
class iPhone
{
// 電量
private $power;
// 充電,只能用原裝的充電器
public function charge()
{
$charger = new AppleCharger;
$this->power = $charger->charge();
}
}
// 充電
$iphone = new iPhone;
$iphone->charge();
使用依賴注入之後,我來決定給 iPhone 用哪一款充電器:
class iPhone
{
private $power;
private $charger;
// 依賴注入充電器,╮(╯▽╰)╭哎算了只要是充電器就行
public function __construct(Charger $charger)
{
$this->charger = $charger;
}
// 充電
public function charge()
{
$this->power = $this->charger->charge();
}
}
interface Charger
{
public function charge();
}
// Laravel 容器
use Illuminate\Container\Container;
$container = Container::getInstance();
// 給它一個原裝充電器:
$container->bind(Charger::class, AppleCharger::class);
// 或者給它其它充電器
$container->bind(Charger::class, OtherCharger::class);
// 充電
$iphone = $container->make(iPhone::class);
$iphone->charger();
可見,使用依賴注入之後,控制權「反轉」了,由外部來決定給它什麼充電器 (依賴物件)。Laravel
管這個 容器控制程式
叫 Service Container (服務容器)
,它來控制著各種依賴的獲取方法。
更多關於 Laravel 依賴注入、服務容器的知識可以參考以前的文章。
Laravel Dependency Injection (依賴注入) 概念詳解
Laravel Container (容器) 概念詳解 (上)
Laravel Container (容器) 深入理解 (下)
依賴注入實現方式:
- 基於建構函式。實現特定引數的建構函式,在新建物件時傳入所依賴型別的物件。
- 基於介面。實現特定介面以供外部容器注入所依賴型別的物件。
- 基於 set 方法。實現特定屬性的 public set 方法,來讓外部容器呼叫傳入所依賴型別的物件。
- 基於註解。基於 Java 的註解功能,在私有變數前加 "@Autowired" 等註解,不需要顯式的定義以上三種程式碼,便可以讓外部容器傳入對應的物件。該方案相當於定義了 public 的 set 方法,但是因為沒有真正的 set 方法,從而不會為了實現依賴注入導致暴露了不該暴露的介面(因為 set 方法只想讓容器訪問來注入而並不希望其他依賴此類的物件訪問)。
依賴查詢:
依賴查詢更加主動,在需要的時候透過呼叫框架提供的方法來獲取物件,獲取時需要提供相關的配置檔案路徑、key等資訊來確定獲取物件的狀態。
本作品採用《CC 協議》,轉載必須註明作者和本文連結