摘要:而依賴倒置原則的思想是,上層不應(yīng)該依賴下層,應(yīng)依賴接口。上面通過(guò)構(gòu)造函數(shù)注入對(duì)象的方式,就是最簡(jiǎn)單的依賴注入當(dāng)然注入不僅可以通過(guò)構(gòu)造函數(shù)注入,也可以通過(guò)屬性注入,上面你可以通過(guò)一個(gè)來(lái)動(dòng)態(tài)為這個(gè)屬性賦值。
依賴倒置和控制反轉(zhuǎn)是一種編程思想,而依賴注入就是通過(guò)服務(wù)容器實(shí)現(xiàn)這種面向接口或者是面向抽象編程的思想概念理解 依賴倒置原則
依賴倒置是一種軟件設(shè)計(jì)思想,在傳統(tǒng)軟件中,上層代碼依賴于下層代碼,當(dāng)下層代碼有所改動(dòng)時(shí),上層代碼也要相應(yīng)進(jìn)行改動(dòng),因此維護(hù)成本較高。而依賴倒置原則的思想是,上層不應(yīng)該依賴下層,應(yīng)依賴接口。意為上層代碼定義接口,下層代碼實(shí)現(xiàn)該接口,從而使得下層依賴于上層接口,降低耦合度,提高系統(tǒng)彈性
控制反轉(zhuǎn)當(dāng)調(diào)用者需要被調(diào)用者的協(xié)助時(shí),在傳統(tǒng)的程序設(shè)計(jì)過(guò)程中,通常由調(diào)用者來(lái)創(chuàng)建被調(diào)用者的實(shí)例,但在這里,創(chuàng)建被調(diào)用者實(shí)例的工作不再由調(diào)用者來(lái)完成,而是將被調(diào)用者的創(chuàng)建移到調(diào)用者的外部,從而反轉(zhuǎn)被調(diào)用者的創(chuàng)建,消除了調(diào)用者對(duì)被調(diào)用者創(chuàng)建的控制,因此稱為控制反轉(zhuǎn)。
要實(shí)現(xiàn)控制反轉(zhuǎn),通常的解決方案是將創(chuàng)建被調(diào)用者實(shí)例的工作交由 IoC 容器來(lái)完成,然后在調(diào)用者中注入被調(diào)用者(通過(guò)構(gòu)造器/方法注入實(shí)現(xiàn)),這樣我們就實(shí)現(xiàn)了調(diào)用者與被調(diào)用者的解耦,該過(guò)程被稱為依賴注入。
依賴注入不是目的,它是一系列工具和手段,最終的目的是幫助我們開發(fā)出松散耦合(loose coupled)、可維護(hù)、可測(cè)試的代碼和程序。這條原則的做法是大家熟知的面向接口,或者說(shuō)是面向抽象編程。
通俗的說(shuō),在調(diào)用一個(gè)對(duì)象的方法,首先要實(shí)例化對(duì)象之后。 而所謂的注入,就是一種工廠模式的升華。由一個(gè)更高級(jí)的工廠(容器),來(lái)完成對(duì)象實(shí)例化,實(shí)現(xiàn)調(diào)用者與被調(diào)用者的解耦解決什么問(wèn)題 實(shí)現(xiàn)調(diào)用者與被調(diào)用者的解耦
[info] 所謂的上層代碼依賴于接口,就是業(yè)務(wù)邏輯的實(shí)現(xiàn)是跳過(guò)了具體對(duì)象的抽象行為。比如我們要對(duì)用戶發(fā)消息,可以通過(guò)郵件發(fā)送,也可以通過(guò)短信發(fā)送。上層代碼不用關(guān)注其用什么發(fā)送,只發(fā)送即可(適配器模式)
interface Mail { public function send(); } class Email implements Mail { public function send() { echo "發(fā)送郵件" . PHP_EOL; } } class SmsMail implements Mail { public function send() { echo "發(fā)送短信" . PHP_EOL; } } // 注冊(cè)容器 class Register { private $_mailObj; // 構(gòu)造函數(shù)里面已經(jīng)約束了必須是實(shí)現(xiàn)了Mail接口的類的實(shí)例 public function __construct(Mail $mailObj) { $this->_mailObj = $mailObj; } public function doRegister() { // 一定會(huì)有send方法 $this->_mailObj->send();//發(fā)送信息 } } $emailObj = new Email(); $smsObj = new SmsMail(); $reg = new Register($emailObj); $reg->doRegister();//使用email發(fā)送 $reg = new Register($smsObj); $reg->doRegister($smsObj);//使用短信發(fā)送
使用構(gòu)造函數(shù)注入的方法,使得它只依賴于發(fā)送短信的接口,只要實(shí)現(xiàn)其接口中的"send"方法,不管你什么方式發(fā)送都可以。上面通過(guò)構(gòu)造函數(shù)注入對(duì)象的方式,就是最簡(jiǎn)單的依賴注入;當(dāng)然"注入"不僅可以通過(guò)構(gòu)造函數(shù)注入,也可以通過(guò)屬性注入,上面你可以通過(guò)一個(gè)"setter"來(lái)動(dòng)態(tài)為"mailObj"這個(gè)屬性賦值。
通過(guò)php反射機(jī)制實(shí)現(xiàn)自動(dòng)注入真實(shí)的dependency injection container會(huì)提供更多的特性,如
自動(dòng)綁定(Autowiring)或 自動(dòng)解析(Automatic Resolution)
注釋解析器(Annotations)
延遲注入(Lazy injection)
c = $c; } public function doSomething() { $this->c->doSomething(); echo __METHOD__ , "我是周伯通B|"; } } class A { private $b; public function __construct(B $b) { $this->b = $b; } public function doSomething() { $this->b->doSomething(); echo __METHOD__ , "我是周伯通A|";; } } class Container { private $s = []; public function __set($k , $c) { $this->s[$k] = $c; } public function __get($k) { return $this->build($this->s[$k]); } /** * 自動(dòng)綁定(Autowiring)自動(dòng)解析(Automatic Resolution) * @param string $className * @return object * @throws Exception */ public function build($className) { // 如果是匿名函數(shù)(Anonymous functions),也叫閉包函數(shù)(closures) if ($className instanceof Closure) { // 執(zhí)行閉包函數(shù),并將結(jié)果 return $className($this); } if(!class_exists($className)){ throw new Exception("{$className} class is not exists"); } /** @var ReflectionClass $reflector */ $reflector = new ReflectionClass($className); // 檢查類是否可實(shí)例化, 排除抽象類abstract和對(duì)象接口interface if (!$reflector->isInstantiable()) { throw new Exception("Can"t instantiate this."); } /** @var ReflectionMethod $constructor 獲取類的構(gòu)造函數(shù) */ $constructor = $reflector->getConstructor(); // 若無(wú)構(gòu)造函數(shù),直接實(shí)例化并返回, (注意! 此處退出遞歸1) if (is_null($constructor)) { return new $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ù)。 return $reflector->newInstanceArgs($dependencies); } /** * @param array $parameters * @return array * @throws Exception */ public function getDependencies($parameters) { $dependencies = []; /** @var ReflectionParameter $parameter */ foreach ($parameters as $parameter) { /** @var ReflectionClass $dependency */ $dependency = $parameter->getClass(); if (is_null($dependency)) { // 是變量,有默認(rèn)值則設(shè)置默認(rèn)值 (注意,此處退出遞歸2) $dependencies[] = $this->resolveNonClass($parameter); } else { // 是一個(gè)類,遞歸解析 $dependencies[] = $this->build($dependency->name); } } return $dependencies; } /** * @param ReflectionParameter $parameter * @return mixed * @throws Exception */ public function resolveNonClass($parameter) { // 有默認(rèn)值則返回默認(rèn)值 if ($parameter->isDefaultValueAvailable()) { return $parameter->getDefaultValue(); } throw new Exception("I have no idea what to do here."); } } /*// example1 $container = new Container(); $container->b = "B"; $container->a = function ($container){ return new A($container->b); }; // 從容器中取得A $model = $container->a; // output: C::doSomething我是周伯通C|B::doSomething我是周伯通B|A::doSomething我是周伯通A| // 實(shí)現(xiàn)依賴自動(dòng)注入 $model->doSomething();*/ // example2 $di = new Container(); $di->php7 = "A"; // 自動(dòng)注入classA /** @var A $php7 */ $foo = $di->php7; $foo->doSomething(); //C::doSomething我是周伯通C|B::doSomething我是周伯通B|A::doSomething我是周伯通A|
參考:
https://www.cnblogs.com/pains...
https://www.cnblogs.com/phppe...
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/31380.html
摘要:起就在中內(nèi)置了服務(wù)器但只是提供開發(fā)測(cè)試使用,不推薦使用中生產(chǎn)環(huán)境中。因?yàn)檫@個(gè)服務(wù)器接受處理請(qǐng)求時(shí)順序執(zhí)行的,不能并發(fā)處理。這個(gè)內(nèi)置的服務(wù)器使用起來(lái)非常的方便,你只需要執(zhí)行下面的命令啟動(dòng)服務(wù)器然后就可以訪問(wèn)了。 PHP 5.4起就在CLI SAPI中內(nèi)置了web服務(wù)器,但只是提供開發(fā)測(cè)試使用,不推薦使用中生產(chǎn)環(huán)境中。因?yàn)檫@個(gè)服務(wù)器接受處理請(qǐng)求時(shí)順序執(zhí)行的,不能并發(fā)處理。 這個(gè)內(nèi)置的web...
摘要:通過(guò)生成器來(lái)生成關(guān)聯(lián)數(shù)組下面每一行是用分號(hào)分割的字段組合,第一個(gè)字段將被用作鍵名。正常來(lái)說(shuō),產(chǎn)生的是一個(gè),它的成員變量與函數(shù)不存在別名引用關(guān)系。關(guān)鍵字在的版本,生成器允許從其他生成器,可迭代對(duì)象或數(shù)組通過(guò)關(guān)鍵字來(lái)生成對(duì)應(yīng)的值輸出 一般你在迭代一組數(shù)據(jù)的時(shí)候,需要?jiǎng)?chuàng)建一個(gè)數(shù)據(jù),假設(shè)數(shù)組很大,則會(huì)消耗很大性能,甚至造成內(nèi)存不足。 //Fatal error: Allowed memory ...
摘要:它使得在生產(chǎn)環(huán)境中啟用斷言為零成本,并且提供當(dāng)斷言失敗時(shí)拋出特定異常的能力。錯(cuò)誤和異常改變了大多數(shù)錯(cuò)誤的報(bào)告方式。不同于傳統(tǒng)的錯(cuò)誤報(bào)告機(jī)制,現(xiàn)在大多數(shù)錯(cuò)誤被作為異常拋出。 PHP7性能 7最大的亮點(diǎn),應(yīng)該就是性能提高了兩倍,某些測(cè)試環(huán)境下甚至提高到三到五倍,具體可以了解以下鏈接: PHP7 VS HHVM (WordPress) HHVM vs PHP 7 – The Competit...
摘要:簡(jiǎn)介是才有的新功能,它是用來(lái)導(dǎo)出或提取出關(guān)于類方法屬性參數(shù)等的詳細(xì)信息,包括注釋。 簡(jiǎn)介 PHP Reflection API是PHP5才有的新功能,它是用來(lái)導(dǎo)出或提取出關(guān)于類、方法、屬性、參數(shù)等的詳細(xì)信息,包括注釋。 class Reflection { } interface Reflector { } class ReflectionException extends Exce...
摘要:實(shí)例化對(duì)象里面的所在哪個(gè)類就返回哪個(gè)類。訪問(wèn)的是當(dāng)前類有點(diǎn)像因?yàn)槠涫抢^承了的方法,而調(diào)用的。由此可見(jiàn),他們的區(qū)別只有在繼承中才能體現(xiàn)出來(lái),如果沒(méi)有任何繼承,那么這兩者是沒(méi)有區(qū)別的。但如果是在靜態(tài)方法內(nèi)本類的話,最好還是用 以static::來(lái)調(diào)用,是在運(yùn)行的那個(gè)時(shí)刻才執(zhí)行綁定操作; 父類中有個(gè)方法是延遲綁定的,在子類::調(diào)用這個(gè)方法的時(shí)候它又回到調(diào)用的子類開始向上找; exampl...
閱讀 3010·2023-04-26 02:49
閱讀 3529·2021-11-25 09:43
閱讀 3721·2021-10-09 09:43
閱讀 3175·2021-09-28 09:44
閱讀 2540·2021-09-22 15:29
閱讀 4737·2021-09-14 18:02
閱讀 2852·2021-09-03 10:48
閱讀 3486·2019-08-30 12:47