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