您好,登錄后才能下訂單哦!
這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)碛嘘P(guān)PHP中的相關(guān)服務(wù)容器與依賴注入的思路,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
依賴注入
當(dāng)A類需要依賴于B類,也就是說需要在A類中實(shí)例化B類的對(duì)象來使用時(shí)候,如果B類中的功能發(fā)生改變,也會(huì)導(dǎo)致A類中使用B類的地方也要跟著修改,導(dǎo)致A類與B類高耦合。這個(gè)時(shí)候解決方式是,A類應(yīng)該去依賴B類的接口,把具體的類的實(shí)例化交給外部。
就拿我們業(yè)務(wù)中常用的通知模塊來說。
<?php /** * 定義了一個(gè)消息類 * Class Message */ class Message{ public function seed() { return '灰太狼準(zhǔn)備吃羊'; } } /* * 訂單產(chǎn)生的時(shí)候 需要發(fā)送消息 */ class Order{ protected $messager = ''; function __construct() { $this->messager = new Message(); } public function seed_msg() { return $this->messager->seed(); } } $Order = new Order(); echo $Order->seed_msg();
上面的代碼是我們傳統(tǒng)的寫法。首先由個(gè)消息發(fā)送的類。然后在我們需要發(fā)送消息的地方,調(diào)用發(fā)送消息的接口。有一天你需要添加一個(gè)發(fā)送短信的接口以滿足不同的需求。那么你會(huì)發(fā)現(xiàn)你要再M(fèi)essage類里面做修改。同樣也要再Order類里面做修改。這樣就顯得很麻煩。這個(gè)時(shí)候就有了依賴注入的思路。
<?php /** * 為了約束我們先定義一個(gè)消息接口 * Interface Message */ interface Message{ public function seed(); } /** * 有一個(gè)發(fā)送郵件的類 * Class SeedEmail */ class SeedEmail implements Message { public function seed() { return '灰太狼發(fā)郵件給紅太狼說要吃烤全羊'; } } /** *新增一個(gè)發(fā)送短信的類 * Class SeedSMS */ class SeedSMS implements Message { public function seed() { return '灰太狼發(fā)短信給紅太狼說要吃烤全羊'; } } /* * 訂單產(chǎn)生的時(shí)候 需要發(fā)送消息 */ class Order{ protected $messager = ''; function __construct(Message $message) { $this->messager = $message; } public function seed_msg() { return $this->messager->seed(); } } //我們需要發(fā)送郵件的時(shí)候 $message = new SeedEmail(); //將郵件發(fā)送對(duì)象作為參數(shù)傳遞給Order $Order = new Order($message); echo $Order->seed_msg(); echo "\n"; //我們需要發(fā)送短信的時(shí)候 $message = new SeedSMS(); $Order = new Order($message); echo $Order->seed_msg();
我理解的服務(wù)容器就是一個(gè)自動(dòng)產(chǎn)生類的工廠。
<?php /** * 為了約束我們先定義一個(gè)消息接口 * Interface Message */ interface Message{ public function seed(); } /** * 有一個(gè)發(fā)送郵件的類 * Class SeedEmail */ class SeedEmail implements Message { public function seed() { return '灰太狼發(fā)郵件給紅太狼說要吃烤全羊'; } } /** *新增一個(gè)發(fā)送短信的類 * Class SeedSMS */ class SeedSMS implements Message { public function seed() { return '灰太狼發(fā)短信給紅太狼說要吃烤全羊'; } } /** * 這是一個(gè)簡(jiǎn)單的服務(wù)容器 * Class Container */ class Container { protected $binds; protected $instances; public function bind($abstract, $concrete) { if ($concrete instanceof Closure) { $this->binds[$abstract] = $concrete; } else { $this->instances[$abstract] = $concrete; } } public function make($abstract, $parameters = []) { if (isset($this->instances[$abstract])) { return $this->instances[$abstract]; } array_unshift($parameters, $this); return call_user_func_array($this->binds[$abstract], $parameters); } } //創(chuàng)建一個(gè)消息工廠 $message = new Container(); //將發(fā)送短信注冊(cè)綁定到工廠里面 $message->bind('SMS',function (){ return new SeedSMS(); }); //將發(fā)送郵件注冊(cè)綁定到工廠 $message->bind('EMAIL',function (){ return new SeedEmail(); }); //需要發(fā)送短信的時(shí)候 $SMS = $message->make('SMS'); echo $SMS->seed(); echo "\n"; $EMAIL = $message->make('EMAIL'); echo $EMAIL->seed();
container是一個(gè)簡(jiǎn)單的服務(wù)容器里面有bind,make兩個(gè)方法
bind是向容器中綁定服務(wù)對(duì)象。
make則是從容器中取出對(duì)象。
在bind方法中需要傳入一個(gè) concrete 我們可以傳入一個(gè)實(shí)例對(duì)象或者是一個(gè)閉包函數(shù)。
可以看到我這全使用的是閉包函數(shù),其實(shí)也可以這樣寫
$sms = new SeedSMS(); $message->bind('SMS',$sms);
后面這種寫法與閉包相比的區(qū)別就是我們需要先實(shí)例化對(duì)象才能往容易中綁定服務(wù)。而閉包則是我們使用這個(gè)服務(wù)的時(shí)候才去實(shí)例化對(duì)象??梢钥闯鲩]包是有很多的優(yōu)勢(shì)的。
make方法就從容器中出去方法。里面首先判斷了instances變量中是否有當(dāng)前以及存在的服務(wù)對(duì)象,如果有直接返回。如果沒有那么會(huì)通過 call_user_func_array返回一個(gè)對(duì)象。call_user_func_array的使用可以查看
PHP 中 call_user_func 的使用
上述就是小編為大家分享的PHP中的相關(guān)服務(wù)容器與依賴注入的思路了,如果剛好有類似的疑惑,不妨參照上述分析進(jìn)行理解。如果想知道更多相關(guān)知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。