欧美成人午夜免费全部完,亚洲午夜福利精品久久,а√最新版在线天堂,另类亚洲综合区图片小说区,亚洲欧美日韩精品色xxx

扣丁學(xué)堂PHP培訓(xùn)之理解并實(shí)現(xiàn)依賴注入容器

2017-12-07 10:10:42 1378瀏覽

  今天扣丁學(xué)堂小編給大家介紹一下關(guān)于PHP培訓(xùn)之實(shí)現(xiàn)依賴注入的詳細(xì)介紹,首先依賴注入可能是我所知道的最簡(jiǎn)單設(shè)計(jì)模式之一,很多情況下可能你無(wú)意識(shí)中已經(jīng)使用了依賴注入。不過(guò)它也是最難解釋的一個(gè)。我認(rèn)為有一部分原因是由于大多數(shù)介紹依賴注入的例子缺乏實(shí)際意義,那么,下面我們來(lái)看一個(gè)簡(jiǎn)單的開(kāi)發(fā)實(shí)例吧。


首先,我們來(lái)看一段代碼:

classA{

publicfunctionecho()

{

echo'A'.PHP_EOL;

}

}

classEchoT{

protected$t;

publicfunction__construct()

{

$this->t=newA();

}

?publicfunctionecho(){

$this->t->echo();

}

?

}

初始,我們都使用new的方式在內(nèi)部進(jìn)行,EchoT類嚴(yán)重依賴于類A。每當(dāng)類A變化時(shí),EchoT類也得進(jìn)行變化。###我們優(yōu)化一下代碼

classEchoT{

protected$t;

publicfunction__construct($t)//構(gòu)造器注入由構(gòu)造器注入到其中

{

$this->t=$t;

}

可以看到,這樣做的話。很大程序上,我們對(duì)程序進(jìn)行了解耦。類A無(wú)論你如何變動(dòng),EchoT類是不需要變動(dòng)的。不再依賴于A。但是新問(wèn)題又來(lái)了,我們現(xiàn)在只有A,萬(wàn)一來(lái)了B,來(lái)了CDEFG怎么辦。

interfaceT{

publicfunctionecho();

}

classA{

publicfunctionecho()

{

echo'A'.PHP_EOL;

}

}

classBimplementsT{

publicfunctionecho()

{

echo'B'.PHP_EOL;

}

}

classEchoT{

protected$t;

publicfunction__construct(T$t)//構(gòu)造器注入由構(gòu)造器注入到其中

{

$this->t=$t;

}

publicfunctionecho(){

$this->t->echo();

}

}

將T抽象出為接口,這樣,EchoT類中的echo方法變成一個(gè)抽象的方法,不到運(yùn)行那一刻,不知道他們的Method方式是怎么實(shí)現(xiàn)的。###工廠

functiongetT($str){

if(class_exists($str)){

returnnew$str();

}

}

T要使用哪個(gè)是不明確的,因此,我們可以將其工廠化?!究瓷先ズ芎?jiǎn)單,在DI實(shí)際上有體現(xiàn)】首先,我們看一下PHP的psr規(guī)范。

官方定義的接口

Psr\Container\ContainerInterface

包含兩個(gè)方法

functionget($id);

functionhas($id);

仔細(xì)看上面的工廠,是不是和get($id)很一致,PHP官方將其定義為容器(Container,我個(gè)人理解,就是一個(gè)復(fù)雜的工廠)

dependencyinjectioncontainer

依賴注入容器

namespaceCore;

usePsr\Container\ContainerInterface;

classContainerimplementsContainerInterface

{

protected$instance=[];//對(duì)象存儲(chǔ)的數(shù)組

publicfunction__construct($path){

$this->_autoload($path);//首先我們要自動(dòng)加載psr-autoload

}

publicfunctionbuild($className)

{

if(is_string($className)and$this->has($className)){

return$this->get($className);

}

//反射

$reflector=new\ReflectionClass($className);

if(!$reflector->isInstantiable()){

thrownew\Exception("Can'tinstantiate".$className);

}

//檢查類是否可實(shí)例化,排除抽象類abstract和對(duì)象接口interface

if(!$reflector->isInstantiable()){

thrownew\Exception("Can'tinstantiate".$className);

}

/**@var\ReflectionMethod$constructor獲取類的構(gòu)造函數(shù)*/

$constructor=$reflector->getConstructor();

//若無(wú)構(gòu)造函數(shù),直接實(shí)例化并返回

if(is_null($constructor)){

returnnew$className;

}

//取構(gòu)造函數(shù)參數(shù),通過(guò)ReflectionParameter數(shù)組返回參數(shù)列表

$parameters=$constructor->getParameters();

//遞歸解析構(gòu)造函數(shù)的參數(shù)

$dependencies=$this->getDependencies($parameters);

//創(chuàng)建一個(gè)類的新實(shí)例,給出的參數(shù)將傳遞到類的構(gòu)造函數(shù)。

$class=$reflector->newInstanceArgs($dependencies);

$this->instance[$className]=$class;

return$class;

}

/**

*@paramarray$parameters

*@returnarray

*/

publicfunctiongetDependencies(array$parameters)

{

$dependencies=[];

/**@var\ReflectionParameter$parameter*/

foreach($parametersas$parameter){

/**@var\ReflectionClass$dependency*/

$dependency=$parameter->getClass();

if(is_null($dependency)){

//是變量,有默認(rèn)值則設(shè)置默認(rèn)值

$dependencies[]=$this->resolveNonClass($parameter);

}else{

//是一個(gè)類,遞歸解析

$dependencies[]=$this->build($dependency->name);

}

}

return$dependencies;

}

/**

*@param\ReflectionParameter$parameter

*@returnmixed

*@throws\Exception

*/

publicfunctionresolveNonClass(\ReflectionParameter$parameter)

{

//有默認(rèn)值則返回默認(rèn)值

if($parameter->isDefaultValueAvailable()){

return$parameter->getDefaultValue();

}

thrownew\Exception($parameter->getName().'mustbenotnull');

}

/**

*參照psr-autoload規(guī)范

*@param$path

*/

publicfunction_autoload($path){

spl_autoload_register(function(string$class)use($path){

$file=DIRECTORY_SEPARATOR.str_replace('\\',DIRECTORY_SEPARATOR,$class).'.php';

if(is_file($path.$file)){

include($path.$file);

returntrue;

}

returnfalse;

});

}

publicfunctionget($id)

{

if($this->has($id)){

return$this->instance[$id];

}

if(class_exists($id)){

return$this->build($id);

}

thrownewClassNotFoundException('classnotfound');//實(shí)現(xiàn)的PSR規(guī)范的異常

}

publicfunctionhas($id)

{

returnisset($this->instance[$id])?true:false;

}

}

####使用示例

$container=newContainer('../');//假設(shè)這是路徑

$echoT=$container->get(\Test\EchoT::class);//假設(shè)echoT類的命名空間是\Test

$echoT->echo();

這個(gè)時(shí)候,會(huì)出現(xiàn)一個(gè)問(wèn)題:

//檢查類是否可實(shí)例化,排除抽象類abstract和對(duì)象接口interface

if(!$reflector->isInstantiable()){

thrownew\Exception("Can'tinstantiate".$className);

}

因?yàn)榻涌赥是無(wú)法實(shí)例化的,所以,一般在程序內(nèi),我們都加上別名(參照l(shuí)aravel框架)

$container->alisa(\Test\T::class,\Test\T\A::class);//指定接口T使用類A(控制反轉(zhuǎn))

####針對(duì)接口下面是alias方法

publicfunctionalias(string$key,$class,bool$singleton=true)

{

if($singleton){

$this->singleton[]=$class;

}

$this->aliases[$key]=$class;

return$this;

}

//同時(shí),我們需要在build的時(shí)候進(jìn)行判斷是否為別名

publicfunctionbuild($className)

{

if(is_string($className)and$this->has($className)){

return$this->get($className);

}

if(isset($this->aliases[$className])){

if(is_object($this->aliases[$className])){

return$this->aliases[$className];

}

$className=$this->aliases[$className];

}

由此可見(jiàn)一個(gè)簡(jiǎn)單的PHP容器就實(shí)現(xiàn)了,以上就是關(guān)于P,最后想要學(xué)習(xí)PHP開(kāi)發(fā)技術(shù)的小伙伴不要猶豫了,扣丁學(xué)堂是你學(xué)習(xí)PHP技術(shù)的最佳選擇,想要PHP視頻教程的小伙伴現(xiàn)在就聯(lián)系我們的咨詢老師領(lǐng)取吧,機(jī)會(huì)總是留給有準(zhǔn)備的人的!扣丁學(xué)堂PHP技術(shù)交流群:374332265。

今天扣丁學(xué)堂小編給大家介紹一下關(guān)于PHP實(shí)現(xiàn)依賴注入的詳細(xì)介紹,首先依賴注入可能是我所知道的最簡(jiǎn)單設(shè)計(jì)模式之一,很多情況下可能你無(wú)意識(shí)中已經(jīng)使用了依賴注入。不過(guò)它也是最難解釋的一個(gè)。我認(rèn)為有一部分原因是由于大多數(shù)介紹依賴注入的例子缺乏實(shí)際意義,那么,下面我們來(lái)看一個(gè)簡(jiǎn)單的開(kāi)發(fā)實(shí)例吧。

首先,我們來(lái)看一段代碼:

classA{

publicfunctionecho()

{

echo'A'.PHP_EOL;

}

}

classEchoT{

protected$t;

publicfunction__construct()

{

$this->t=newA();

}

?publicfunctionecho(){

$this->t->echo();

}

?

}

初始,我們都使用new的方式在內(nèi)部進(jìn)行,EchoT類嚴(yán)重依賴于類A。每當(dāng)類A變化時(shí),EchoT類也得進(jìn)行變化。###我們優(yōu)化一下代碼

classEchoT{

protected$t;

publicfunction__construct($t)//構(gòu)造器注入由構(gòu)造器注入到其中

{

$this->t=$t;

}

可以看到,這樣做的話。很大程序上,我們對(duì)程序進(jìn)行了解耦。類A無(wú)論你如何變動(dòng),EchoT類是不需要變動(dòng)的。不再依賴于A。但是新問(wèn)題又來(lái)了,我們現(xiàn)在只有A,萬(wàn)一來(lái)了B,來(lái)了CDEFG怎么辦。

interfaceT{

publicfunctionecho();

}

classA{

publicfunctionecho()

{

echo'A'.PHP_EOL;

}

}

classBimplementsT{

publicfunctionecho()

{

echo'B'.PHP_EOL;

}

}

classEchoT{

protected$t;

publicfunction__construct(T$t)//構(gòu)造器注入由構(gòu)造器注入到其中

{

$this->t=$t;

}

publicfunctionecho(){

$this->t->echo();

}

}

將T抽象出為接口,這樣,EchoT類中的echo方法變成一個(gè)抽象的方法,不到運(yùn)行那一刻,不知道他們的Method方式是怎么實(shí)現(xiàn)的。###工廠

functiongetT($str){

if(class_exists($str)){

returnnew$str();

}

}

T要使用哪個(gè)是不明確的,因此,我們可以將其工廠化?!究瓷先ズ芎?jiǎn)單,在DI實(shí)際上有體現(xiàn)】首先,我們看一下PHP的psr規(guī)范。

官方定義的接口

Psr\Container\ContainerInterface

包含兩個(gè)方法

functionget($id);

functionhas($id);

仔細(xì)看上面的工廠,是不是和get($id)很一致,PHP官方將其定義為容器(Container,我個(gè)人理解,就是一個(gè)復(fù)雜的工廠)

dependencyinjectioncontainer

依賴注入容器

namespaceCore;

usePsr\Container\ContainerInterface;

classContainerimplementsContainerInterface

{

protected$instance=[];//對(duì)象存儲(chǔ)的數(shù)組

publicfunction__construct($path){

$this->_autoload($path);//首先我們要自動(dòng)加載psr-autoload

}

publicfunctionbuild($className)

{

if(is_string($className)and$this->has($className)){

return$this->get($className);

}

//反射

$reflector=new\ReflectionClass($className);

if(!$reflector->isInstantiable()){

thrownew\Exception("Can'tinstantiate".$className);

}

//檢查類是否可實(shí)例化,排除抽象類abstract和對(duì)象接口interface

if(!$reflector->isInstantiable()){

thrownew\Exception("Can'tinstantiate".$className);

}

/**@var\ReflectionMethod$constructor獲取類的構(gòu)造函數(shù)*/

$constructor=$reflector->getConstructor();

//若無(wú)構(gòu)造函數(shù),直接實(shí)例化并返回

if(is_null($constructor)){

returnnew$className;

}

//取構(gòu)造函數(shù)參數(shù),通過(guò)ReflectionParameter數(shù)組返回參數(shù)列表

$parameters=$constructor->getParameters();

//遞歸解析構(gòu)造函數(shù)的參數(shù)

$dependencies=$this->getDependencies($parameters);

//創(chuàng)建一個(gè)類的新實(shí)例,給出的參數(shù)將傳遞到類的構(gòu)造函數(shù)。

$class=$reflector->newInstanceArgs($dependencies);

$this->instance[$className]=$class;

return$class;

}

/**

*@paramarray$parameters

*@returnarray

*/

publicfunctiongetDependencies(array$parameters)

{

$dependencies=[];

/**@var\ReflectionParameter$parameter*/

foreach($parametersas$parameter){

/**@var\ReflectionClass$dependency*/

$dependency=$parameter->getClass();

if(is_null($dependency)){

//是變量,有默認(rèn)值則設(shè)置默認(rèn)值

$dependencies[]=$this->resolveNonClass($parameter);

}else{

//是一個(gè)類,遞歸解析

$dependencies[]=$this->build($dependency->name);

}

}

return$dependencies;

}

/**

*@param\ReflectionParameter$parameter

*@returnmixed

*@throws\Exception

*/

publicfunctionresolveNonClass(\ReflectionParameter$parameter)

{

//有默認(rèn)值則返回默認(rèn)值

if($parameter->isDefaultValueAvailable()){

return$parameter->getDefaultValue();

}

thrownew\Exception($parameter->getName().'mustbenotnull');

}

/**

*參照psr-autoload規(guī)范

*@param$path

*/

publicfunction_autoload($path){

spl_autoload_register(function(string$class)use($path){

$file=DIRECTORY_SEPARATOR.str_replace('\\',DIRECTORY_SEPARATOR,$class).'.php';

if(is_file($path.$file)){

include($path.$file);

returntrue;

}

returnfalse;

});

}

publicfunctionget($id)

{

if($this->has($id)){

return$this->instance[$id];

}

if(class_exists($id)){

return$this->build($id);

}

thrownewClassNotFoundException('classnotfound');//實(shí)現(xiàn)的PSR規(guī)范的異常

}

publicfunctionhas($id)

{

returnisset($this->instance[$id])?true:false;

}

}

####使用示例

$container=newContainer('../');//假設(shè)這是路徑

$echoT=$container->get(\Test\EchoT::class);//假設(shè)echoT類的命名空間是\Test

$echoT->echo();

這個(gè)時(shí)候,會(huì)出現(xiàn)一個(gè)問(wèn)題:

//檢查類是否可實(shí)例化,排除抽象類abstract和對(duì)象接口interface

if(!$reflector->isInstantiable()){

thrownew\Exception("Can'tinstantiate".$className);

}

因?yàn)榻涌赥是無(wú)法實(shí)例化的,所以,一般在程序內(nèi),我們都加上別名(參照l(shuí)aravel框架)

$container->alisa(\Test\T::class,\Test\T\A::class);//指定接口T使用類A(控制反轉(zhuǎn))

####針對(duì)接口下面是alias方法

publicfunctionalias(string$key,$class,bool$singleton=true)

{

if($singleton){

$this->singleton[]=$class;

}

$this->aliases[$key]=$class;

return$this;

}

//同時(shí),我們需要在build的時(shí)候進(jìn)行判斷是否為別名

publicfunctionbuild($className)

{

if(is_string($className)and$this->has($className)){

return$this->get($className);

}

if(isset($this->aliases[$className])){

if(is_object($this->aliases[$className])){

return$this->aliases[$className];

}

$className=$this->aliases[$className];

}

        由此可見(jiàn)一個(gè)簡(jiǎn)單的PHP容器就實(shí)現(xiàn)了,以上就是關(guān)于P,最后想要學(xué)習(xí)PHP開(kāi)發(fā)技術(shù)的小伙伴不要猶豫了,扣丁學(xué)堂是你學(xué)習(xí)PHP技術(shù)的最佳選擇,想要PHP視頻教程的小伙伴現(xiàn)在就聯(lián)系我們的咨詢老師領(lǐng)取吧,機(jī)會(huì)總是留給有準(zhǔn)備的人的!扣丁學(xué)堂PHP技術(shù)交流群:374332265。



【關(guān)注微信公眾號(hào)免費(fèi)領(lǐng)取丁豆獲取更多的學(xué)習(xí)資料】



查看更多關(guān)于“php培訓(xùn)資訊的相關(guān)文章>>

標(biāo)簽: PHP培訓(xùn) PHP視頻教程 PHP開(kāi)發(fā)培訓(xùn)

熱門專區(qū)

暫無(wú)熱門資訊

課程推薦

微信
微博
15311698296

全國(guó)免費(fèi)咨詢熱線

郵箱:codingke@1000phone.com

官方群:148715490

北京千鋒互聯(lián)科技有限公司版權(quán)所有   北京市海淀區(qū)寶盛北里西區(qū)28號(hào)中關(guān)村智誠(chéng)科創(chuàng)大廈4層
京ICP備2021002079號(hào)-2   Copyright ? 2017 - 2022
返回頂部 返回頂部