摘要: 控制反轉(inversion of control,英文縮寫為ioc)是框架的重要特徵。控制反轉(ioc)是一種思想,依賴注入(di)是實施這種思想的方法。
高層模組不應該依賴於底層模組,兩個都應該依賴抽象。
抽象不應該依賴於細節,細節應該依賴於抽象。
首先,我們來看一段**:
class a} class echot
public
function echo()
} 初始,我們都使用new 的方式在內部進行,echot類嚴重依賴於類a。每當類a變化時,echot類也得進行變化。
我們優化一下**
class echot可以看到,這樣做的話。很大程式上,我們對程式進行了解耦。類a無論你如何變動,echot類是不需要變動的。不再依賴於a。但是新問題又來了,我們現在只有a,萬一來了b,來了cdefg怎麼辦。
面向介面
inte***ce tclass a
} class b implements t
} class echot
public
function echo()
} 將t抽象出為介面,這樣,echot類中的echo方法變成乙個抽象的方法,不到執行那一刻,不知道他們的method方式是怎麼實現的。
工廠
function gett($str)} t要使用哪個是不明確的,因此,我們可以將其工廠化。【看上去很簡單,在di實際上有體現】
di(重點來了)
首先,我們看一下php的psr規範。
官方定義的介面
psr\container\containerinte***ce
包含兩個方法
function get($id);
function has($id);
仔細看上面的工廠,是不是和get($id)很一致,php官方將其定義為容器(container,我個人理解,就是乙個複雜的工廠)
dependency injection container
依賴注入容器
namespace core;use psr\container\containerinte***ce;
class container implements containerinte***ce
public
function build($classname)
//反射
$reflector = new \reflectionclass($classname);
if (!$reflector->isinstantiable())
// 檢查類是否可例項化, 排除抽象類abstract和物件介面inte***ce
if (!$reflector->isinstantiable())
/** @var \reflectionmethod $constructor 獲取類的建構函式 */
$constructor = $reflector->getconstructor();
// 若無建構函式,直接例項化並返回
if (is_null($constructor))
// 取構造函式引數,通過 reflectionparameter 陣列返回引數列表
$parameters = $constructor->getparameters();
// 遞迴解析建構函式的引數
$dependencies = $this->getdependencies($parameters);
// 建立乙個類的新例項,給出的引數將傳遞到類的建構函式。
$class = $reflector->newinstanceargs($dependencies);
$this->instance[$classname] = $class;
return $class;
} /**
* @param array $parameters
* @return array
*/ public
function getdependencies(array $parameters)
else
} return $dependencies;
} /**
* @param \reflectionparameter $parameter
* @return mixed
* @throws \exception
*/ public
function resolvenonclass(\reflectionparameter $parameter)
throw new \exception($parameter->getname().' must be not null');
} /**
* 參照psr-autoload規範
* @param $path
*/ public
function _autoload($path)
return
false;
});
} public
function get($id)
if(class_exists($id))
throw new classnotfoundexception('class not found'); //實現的psr規範的異常
} public
function has($id)
} 使用示例
$container = new container('../');//假設這是路徑$echot = $container->get(\test\echot::class); //假設echot類的命名空間是\test
$echot->echo();
這個時候,會出現乙個問題:
// 檢查類是否可例項化, 排除抽象類abstract和物件介面inte***ceif (!$reflector->isinstantiable())
$this->aliases[$key] = $class;
return $this;
} //同時,我們需要在build的時候進行判斷是否為別名
public
function build($classname)
if(isset($this->aliases[$classname]))
$classname = $this->aliases[$classname];
}
就此,乙個簡單的php容器就實現了。
php 依賴注入的實現
當a類需要依賴於b類,也就是說需要在a類中例項化b類的物件來使用時候,如果b類中的功能發生改變,也會導致a類中使用b類的地方也要跟著修改,導致a類與b類高耦合。這個時候解決方式是,a類應該去依賴b類的介面,把具體的類的例項化交給外部。為了約束我們先定義乙個訊息介面 inte ce message i...
php依賴注入
依然是來自到喜啦的一道面試題,你知道什麼是依賴注入嗎?依賴注入 di 的概念雖然聽起來很深奧,但是如果你用過一些新興的php框架的話,對於di一定不陌生,因為它們多多少少都用到了依賴注入來處理類與類之間的依賴關係。class a 為什麼這種方案不可取呢?因為這樣的話,a與b就耦合在了一起,也就是說a...
如何理解php的依賴注入
之前寫過關於php依賴注入的文章。最近發現有的朋友對這個還是理解模糊,在這裡我想寫個簡單的例項幫助朋友們理解下。傳統的思路是應用程式用到乙個a類,就會建立a類並呼叫a類的方法,假如這個方法內需要乙個b類,就會建立b類並呼叫b類的方法,而這個方法內需要乙個c類,就會建立c類,接著做些其它工作。clas...