摘要:在本篇,我嘗試用另一種方式實現。自動注入可以簡單理解為可以復用的方法,下面來看看怎么用來實現自動注入。
這里先假設一個場景:
有一個工廠(Factory),需要工人(Worker) 使用某個機器(Machine)來生產某種產品
即有這樣的依賴關系: Factory --> Worker --> Machine
不使用注入代碼大概是這樣子:
class Machine{ function run(){ echo "機器開動"; } } class Worker { function work(){ echo "工人開動機器 -> "; $machine = new Machine(); $machine -> run(); } } class Factory{ function produce(){ echo "工廠叫工人開工 -> "; $worker = new Worker(); $worker -> work(); } } $factory = new Factory(); $factory -> produce();
可以看出來,這里所依賴的對象都由類自己在內部實例化,是一種強耦合,不利于測試和維護。比如我現在要改成另一種工人來生產,那就要改工廠內部,這是不合理的。
手工注入所謂的注入,就是將類所依賴的對象的實例化操作放在類外面,同時使用Interface來作出約束:
Interface Machine{ public function run(); } Interface Worker{ public function work(); } class Machine1 implements Machine{ function run(){ echo "機器 1 開動"; } } class Machine2 implements Machine{ function run(){ echo "機器 2 開動"; } } class Worker1 implements Worker{ private $machine; public function __construct(Machine $machine){ $this -> machine = $machine; } function work(){ echo "工人 1 開動機器 -> "; $this -> machine -> run(); } } class Worker2 implements Worker{ private $machine; public function __construct(Machine $machine){ $this -> machine = $machine; } function work(){ echo "工人 2 開動機器 -> "; $this -> machine -> run(); } } class Factory{ private $worker; public function __construct(Worker $worker){ $this -> worker = $worker; } function produce(){ echo "工廠叫工人開工 -> "; $this -> worker -> work(); } } $machine = new Machine1(); $worker = new Worker2($machine); $factory = new Factory($worker); $factory -> produce();
可以看出來,這樣的好處是解耦。比如:可以由工人1開動機器2來生產,也可以由工人2來開動機器1來生產,以后也可以隨時用新的工人(只要他會work)、Worker也可以隨時換其它的機器(只要它會run)來生產。這種轉換都不需要修改工廠或工人的代碼。
那么問題來了,現在只是把實例化從里面移到了外面,但如果依賴的東西多了,也是很麻煩的,這就需要一個自動注入的機制,也就是平時經常聽到的注入容器,常見的容器都是用到反射來實現,而且要在構造函數中聲明注入的類型,相對還是比較麻煩。
在本篇,我嘗試用另一種方式實現。
trait自動注入trait可以簡單理解為可以復用的方法,下面來看看怎么用trait來實現自動注入。
思路就是用trait來實現魔術方法__get,通過該方法來自動生成依賴的對象,先看完整代碼
trait DI{ private $map = ["Worker" => "Worker1","Machine"=>"Machine2"]; function __get($k){ if(preg_match("/^[A-Z]/", $k)) { $obj = new $this -> map[$k]; if($obj instanceof $k){ return $obj; }else{ exit("不符約定"); } } } } Interface Machine{ public function run(); } Interface Worker{ public function work(); } class Machine1 implements Machine{ function run(){ echo "機器 1 開動"; } } class Machine2 implements Machine{ function run(){ echo "機器 2 開動"; } } class Worker1 implements Worker{ use DI; function work(){ echo "工人 1 開動機器 -> "; $this -> Machine -> run(); } } class Worker2 implements Worker{ use DI; function work(){ echo "工人 2 開動機器 -> "; $this -> Machine -> run(); } } class Factory{ use DI; function produce(){ echo "工廠叫工人開工 -> "; $this -> Worker -> work(); } } $factory = new Factory(); $factory -> produce();
trait中的map用來演示實現類和接口的綁定關系,以便進行類型約束,實際應用時可以用配置或其它方式實現.
類中要使用依賴注入時,需聲明use DI, 同時,注入的對象為首字母大寫(你也可以用其它規則,相應的修改trait中的判斷)
當然了,這只是一個很粗糙的演示,只實現了基本的自動注入,它還有很多問題,比如原來的類如果也有__get方法時,就會產生覆蓋。
有興趣的可以嘗試完善一下看能不能在項目中實際使用。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/28396.html
摘要:判斷是否存在構造函數,不存在直接實例化,存在則通過來獲取輸入函數,并有相應的方法解決依賴參數問題,實現依賴注入。 Laravel 框架關鍵技術解析·讀書筆記(一) 第一章 入口文件 請求訪問的入口文件,主要完成幾部分工作,分別是: 自動加載函數的添加 服務器實例化與服務注冊 路由加載 請求實例化與路由分發 相應生成與發送 其中,自動加載函數用于包含引用文件,改文件是composer...
摘要:在閱讀文檔的時候看到一個類是以聲明的。是一種代碼復用技術,為的單繼承限制提供了一套靈活的代碼復用機制。下面把的代碼做一個修改以上代碼會輸出??梢钥闯鰞炏燃壍捻樞驗?,當前類的優先級基類。 ??在閱讀laravel文檔的時候看到一個類 是以 Trait聲明的。平時在工作中從來沒有用過,于是就去看了下官方文檔。原來這個類早在php5.4.0就有了??上г陧椖恐袕膩頉]有用過。 ??Trait看...
摘要:和組合的語義定義了一種減少復雜性的方式,避免傳統多繼承和類相關典型問題。隊列的目的是將耗時的任務延時處理,比如發送郵件,從而大幅度縮短請求和相應的時間。同樣的道理,根據引入不同的來完成對應的功能。 showImg(https://segmentfault.com/img/remote/1460000010868178); Trait 概念 在常規的 PHP 開發中,我們都習慣于先編寫一...
摘要:事件將通過添加關注來激活。自動注冊事件監聽器通過使用,你可以自動注冊事件監聽器,而不需要使用。你可以自由使用這個宏,或者創造你自己的語法以上例子可作對于方法可查看文檔測試測試下載測試存儲導出測試隊列導出 Basics 最簡單的導出方法是創建一個自定義的導出類, 這里我們使用發票導出作為示例. 在 App/Exports 下創建一個 InvoicesExport 類 namespace...
摘要:很多開發朋友都沒有弄清楚性狀。性狀有兩個作用表明類可以做什么像是接口提供模塊化實現像是類。注是不要自我重復的簡稱,表示不要在多個地方重復編寫相同的代碼,如果需要修改遵守這個原則編寫的代碼,只需要在一出修改,改動就能體現到其他地方。 很多PHP開發朋友都沒有弄清楚Trait(性狀)。這是PHP5.4.0引入的新概念,既像類又像接口。性狀是類的補分實現(即常量、屬性、方法),可以混入一個...
閱讀 4391·2021-11-19 09:59
閱讀 3320·2021-10-12 10:12
閱讀 2631·2021-09-22 15:25
閱讀 3321·2019-08-30 15:55
閱讀 1183·2019-08-29 11:27
閱讀 1463·2019-08-28 18:06
閱讀 2736·2019-08-26 13:41
閱讀 2555·2019-08-26 13:41