控制反轉(簡稱IoC),是一種面向對象的設計思想,用來下降代碼間的耦合度。經過控制反轉,對象在被建立的時候,由一個調控系統內全部對象的外界實體,將其所依賴的對象的引用傳遞給它。也就是將依賴被注入到要調用的對象中。控制反轉通常和容器思想結合使用,Ioc就是將對象交給容器去控制,而不是在對象內部直接控制,主要是控制對象的內部依賴。
php
IoC經過一個專門的容器來建立對象,經過IoC容器來控制對象laravel
控制實例的外部依賴編程
關於反轉設計模式
IoC是一種面向對象的變成思想和指導準則。解決傳統控制正轉開發中在類內部主動建立依賴類,從而致使類的內部耦合,難以複用。IoC把查找建立依賴的控制權反轉給容器,由容器進行注入來組合建立一個對象,不一樣需求容器能夠注入不一樣的對象,從而消除對象和依賴的耦合。數組
依賴注入指容器在運行中動態的將依賴注入到組件中,從而使組件具備具體的功能。經過依賴注入能夠在特殊的地方指定同一個抽象方法去處理不一樣依賴對象的邏輯,而不須要了解和修改具體抽象方法的實現,只須要關注本身的業務層。框架
實例化類依賴控制容器函數
實例化類須要依賴其餘資源才能夠處理具體業務this
IoC容器向實例化類中注入了某個依賴spa
set
方法。實現特定屬性的 public set
方法,來讓外部容器調用傳入所依賴類型的對象。interface Way { public function go(); } class GoShanghai { private $charger; public function __construct(Way $charger) { $this->charger = $charger; } public function setWay(Way $way) { $this->way = $way; } public function go() { $this->charger->go(); } } class Car implements Way { public function go() { // TODO: Implement go() method. print_r("我經過開車去上海"); } }
// 基於構造函數和接口 $goshanghai = new GoShanghai(new Car()); $goshanghai->go(); // 基於set方法|展現須要由於構造函數運行會出錯 $goshanghai = new GoShanghai(); $goshanghai->setWay(new Car()); $goshanghai->go();
依賴查找更加主動,在須要的時候經過調用框架提供的方法來獲取對象,獲取時須要提供相關的配置文件路徑、key等信息來肯定獲取對象的狀態。
觀察者模式主要用於處理對象直接一對多多關係。當外部資源發生改變,觀察者會獲得通知。觀察者和被觀察者直接是抽象耦合的,也就不影響實例的解藕。
觀察者是一對多關係中的多,觀察者須要根據目標對象改變而改變的對象。
觀察目標對象的某些特定的狀態。
觀察者繼承自一個抽象觀察類,抽象觀察類實現註冊、監聽和通知功能。
/** * 觀察者的抽象類 */ abstract class Observer { // 這是一個目標類 protected $subject; // 定義一個用於更新的抽象方法 public abstract function update(); } /** * 目標類 */ class Subject { // 觀察者數組集合 private $observerList = array(); // 狀態,這裏遵循開閉原則將屬性私有化 private $state = 0; /** * 獲取狀態的值 */ public function getState() :int { return $this->state; } /** * 設置狀態的值 * @param int $state */ public function setState(int $state) { $this->state = $state; $this->notifyAllObservers(); } /** * 註冊觀察者 * @param Observer $observer */ public function attach(Observer $observer) { array_push($this->observerList, $observer); } /** * 通知觀察者 */ public function notifyAllObservers() { foreach ($this->observerList as $observer) { $observer->update(); } } } /** * 觀察者A */ class AObserver extends Observer { public function __construct(Subject $subject) { // 注入目標依賴實現IoC $this->subject = $subject; // 註冊觀察者 $this->subject->attach($this); } public function update() { // TODO: Implement update() method. print_r("A觀察者更新了支付業務的狀態:{$this->subject->getState()}\n"); } }
// 建立一個目標對象 $subject = new Subject(); // 爲目標對象綁定觀察者 new AObserver($subject); print_r("目標對象的狀態:{$subject->getState()}\n"); $subject->setState(10); // 目標對象的狀態:0 // A觀察者更新了支付業務的狀態:10
經過一個抽象基類定義執行它的模版也能夠是方法,子類重寫抽象方法的實現,但調用實在抽象基類中完成的,從而實現控制反轉。就是基類控制行爲,子類完成實現。
/** * 抽象模版類 */ abstract class Template { // 抽象方法A public abstract function stepA(); // 抽象方法B public abstract function stepB(); // 執行定義的步驟, 這裏使用了final關鍵字修飾,final的做用是使這個方法不可被繼承, 這樣就不會被子類執行 public final function run() { $this->stepA(); $this->stepB(); } } /** * 方案A的實例 */ class FuncA extends Template { public function stepA() { // TODO: Implement stepA() method. print_r("方案A第一步\n"); } public function stepB() { // TODO: Implement stepB() method. print_r("方案A第二步\n"); } }
$funca = new FuncA(); $funca->run();
上面的例子能夠看到控制反轉使每一個業務實例相對對立,他們的組裝在代碼執行時完成,當業務簡單、依賴單一時看上去沒有問題,可是當依賴複雜時會致使組裝變得繁瑣且難以梳理。在laravel中是經過容器Container
來解決這個問題。下面咱們經過幾句話來簡單看一下laravel中容器的使用。
laravel
時就是啓動了一個容器make
實現自動序列化依賴對象,代替new
bind
方法讓每個抽象接口和它的實例類一一對應resolveing
方法註冊一個回調callback
在綁定的對象解析完以後調用