什麼是IOC容器

控制反轉(IOC)

想知道什麼叫控制反轉就先明白什麼叫控制不反轉(實在想不出應該怎麼叫啦,明白意思就好,不必糾結用詞雅不雅)我們舉個例子看一下,假如我們想要生產一部手機,每款手機只存在系統的差異

class Ios{
	public function getSystemMark(){
		echo "This is a ios Phone";
	}
}

class Android{
	public function getSystemMark(){
		echo "This is a android Phone";
	}
}

class Phone{
	public function make(){
		$ios = new Ios();
		$ios->getSystemMark();
	}
}

//產一部蘋果手機
$ios_phone = new Phone();
$ios_phone->make();

對於上面這種當實例化phone類並且調用其中make方法時 對象會主動的在類的內部獲取所需要的外部資源(這裏指由Ios類實例化出來的對象),這種情況就叫做控制不反轉

  • 對於這種情況下有一種弊端就是當我們想要生產一部android手機時需要修改phone類中的make方法這樣的話就是的代碼的耦合率更加的大。這樣的話如果想要生產多種系統的手機的話豈不是很麻煩,這個問題要怎麼解決呢??接在來就是控制反轉登場的時刻啦!看改良後的代碼
  • interface System{
    	public function getSystemMark();
    }
    
    class Ios implements System{
    	public function getSystemMark(){
    		echo "This is a ios Phone";
    	}
    }
    
    class Android implements System{
    	public function getSystemMark(){
    		echo "This is a android Phone";
    	}
    }
    
    class Phone{
    	protected $system;
    	public function __construct(System $system){
    		$this->system = $system;
    	}
    
    	public function make(){
    		$this->system->getSystemMark();
    	}
    }
    
    $ios = new Ios();
    $ios_phome = new Phone($ios);
    $ios_phome->make();
    
    $android = new Android();
    $android_phone = new Phone($android);
    $android_phone->make();

     

  • 現在我們在實例化phone類的時候就不用在make的內部去實例化相應的系統類啦!這種由外部提供對象所需資源(這裏指 系統對象)的情況叫做控制反轉,實現控制反轉的方式叫做依賴注入(DI)
  • phone類實例化的對象調用make方法時,make方法的實現依賴於 系統類所實例化得到的對象,但是這種對象不是有phone類內部實例化獲得的,而是在外部實例化夥的然後通過構造方法傳入進對象的內部的,這種方式叫做依賴注入。
  • 好啦!知道了什麼叫做控制反轉、依賴注入後讓我們來看看怎麼把代碼再優化一下。上面的代碼雖然我們實現了IOC和DI,但是當我們獲取一個手機時還要自己去手動實例化 ios android的類然後再實例化phone,這麼做太不智能啦!但是我們怎麼來讓它更好一些呢!這時候我們使用IOC容器來實現就可以啦,下面代碼:

  • interface System{
    	public function getSystemMark();
    }
    
    class Ios implements System{
    	public function getSystemMark(){
    		echo "This is a ios Phone";
    	}
    }
    
    class Android implements System{
    	public function getSystemMark(){
    		echo "This is a android Phone";
    	}
    }
    
    class Phone{
    	protected $system;
    	public function __construct(System $system){
    		$this->system = $system;
    	}
    
    	public function make(){
    		$this->system->getSystemMark();
    	}
    }
    
    class Container{
    	private $instances;
    	private $binds;
    
    	public function binds($abstract,$concrete){
    		if($concrete instanceof Closure){
    			$this->binds[$abstract] = $concrete;
    		}else{
    			$this->instances[$abstract] = $concrete;
    		}
    		
    	}
    
    	public function make($abstract,$params = []){
    		if(isset($this->instances[$abstract])){
    			return $this->instances[$abstract];
    		}
    
    		if($params){
    			$params = [$params];
    			array_unshift($params, $this);
    			return call_user_func_array($this->binds[$abstract],$params);
    		}else{
    			return call_user_func($this->binds[$abstract]);
    		}
    		
    	}
    
    }
    
    $container = new Container();
    $container->binds("phone",function($container,$system){
    	return new Phone($container->make($system));
    });
    
    $container->binds("ios",function(){
    	return new Ios();
    });
    
    $container->binds("android",function(){
    	return new Android();
    });
    
    $ios_phone = $container->make("phone","ios");
    $android_phone = $container->make("phone","android");
    
    $ios_phone->make();
    $android_phone->make();

    ok!ioc容器的簡單實現就完成啦!更高級的IOC容器要使用類的反射來做

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章