詳解Laravel服務(wù)容器的優(yōu)勢
概述
laravel服務(wù)容器就像一個(gè)高度自動化的工廠,你需要的東西,定制好模型,使用特定接口來制造。
因?yàn)槭褂昧朔?wù)容器,laravel中大部分對象實(shí)例化的方式是這樣的:
$obj1 = $container->make('class1', 'class2'); $obj2 = $container->make('class3', 'class4');
但是在沒有使用服務(wù)容器的情況下,以下這種方式同樣可以做到:
$obj1 = new class1(new class2()); $obj2 = new class3(new class4());
使用服務(wù)容器的優(yōu)勢
下面我們通過一些具體例子來分析下它的優(yōu)勢:
例一、發(fā)送郵件
我們把發(fā)送郵件的功能封裝成一個(gè)類,需要使用的時(shí)候,實(shí)例化并調(diào)用發(fā)送方法。
以下是不使用laravel服務(wù)容器常見的方式:
/** *發(fā)送郵件服務(wù)類 */ class EmailService{ public function send(){ //todo 發(fā)送郵件方法 } } //如果任何地方要發(fā)郵件我們就復(fù)制下面這兩行代碼 $emailService = new EmailService(); $emailService->send();
使用了laravel服務(wù)容器以后:
$this->app->bind('emailService', function ($app) { return new EmailService(); }); //如果任何地方要發(fā)郵件我們就復(fù)制下面這兩行代碼 $emailService = app('emailService'); $emailService->send();
這使得我們的代碼更加簡潔了,并且由于有了中間層,靈活性提高了(解耦),那么無論是測試(在測試時(shí)我們可以偽造類替換EmailService類)還是優(yōu)化EmailService類,都變得更加方便。
//只需要改這一個(gè)地方 $this->app->bind('emailService', function ($app) { return new SupperEmailService(); });
其他調(diào)用的部分我們完全不用動,如果我們沒有這個(gè)綁定操作,那么不得不在每個(gè)使用郵件服務(wù)的地方做更改。
//使用到EamilSerice類的每個(gè)地方都要更改 $emailService = new SupperEmailService(); $emailService->send();
例二、實(shí)現(xiàn)單例模式
還是上面的例子,出于性能的考慮,你需要SupperEamilService類實(shí)現(xiàn)單例模式,于是在不使用laravel服務(wù)容器的情況下,你將SupperEmailService類更改如下:
class SupperEamilService{ //創(chuàng)建靜態(tài)私有的變量保存該類對象 static private $instance; //防止直接創(chuàng)建對象 private function __construct(){ } //防止克隆對象 private function __clone(){ } static public function getInstance(){ //判斷$instance是否是Uni的對象 //沒有則創(chuàng)建 if (!self::$instance instanceof self) { self::$instance = new self(); } return self::$instance; } //發(fā)送郵件方法 public function send(){ } }
除此之外,由于現(xiàn)在SupperEamilService類構(gòu)造函數(shù)為私有,無法通過new關(guān)鍵字來實(shí)例化對象,所以在每個(gè)實(shí)例化SupperEmailService類的地方都要改成這樣:
$emailService=SupperEmailService::getInstance(); $emailService->send();
laravel服務(wù)容器天生支持單例,下面是laravel的實(shí)現(xiàn)方式:
//只需要把bind改成singleton $this->app->singleton('emailService', function ($app) { return new SupperEmailService(); });
要實(shí)現(xiàn)單例甚至只需要改一行代碼,把原來的bind方法改成singleton ,通過容器取出來的便是單例,真是太方便了。
例三、旅行者去旅行
這個(gè)例子假設(shè)一個(gè)旅行者去西藏旅行,可以做火車(train)或者走路(leg)去。
不使用laravel服務(wù)容器:
<?php interface TrafficTool{ public function go(); } class Train implements TrafficTool{ public function go(){ echo "train...."; } } class Leg implements TrafficTool{ public function go(){ echo "leg.."; } } class Traveller{ /** * @var Leg|null|Train * 旅行工具 */ protected $_trafficTool; public function __construct(TrafficTool $trafficTool){ $this->_trafficTool = $trafficTool; } public function visitTibet() { $this->_trafficTool->go(); } }
當(dāng)旅行者要坐火車去旅行通常我們這樣寫:
<?php $train = new Train(); $tra = new Traveller($train); $tra->visitTibet();
事實(shí)上這種寫法已經(jīng)非常不錯(cuò)了,因?yàn)閷τ诼眯泄ぞ叩囊蕾囈呀?jīng)通過接口的方式轉(zhuǎn)移到外部了。但是使用new來實(shí)例化對象的時(shí)候還是會產(chǎn)生依賴.比如上面trafficTool),這說明我們要?jiǎng)?chuàng)建一個(gè)Traveller之前必須得有一個(gè)$trafficTool,即Traveller依賴于trafficTool.當(dāng)使用new來實(shí)例化Traveller的時(shí)候,Traveller和trafficTool之間就產(chǎn)生了耦合.這樣,這兩個(gè)組件就沒辦法分開了。
現(xiàn)在我們來看看使用laravel服務(wù)容器是怎么實(shí)現(xiàn)的:
在服務(wù)容器中綁定類
<?php namespace App\Providers; use Laravel\Lumen\Providers\EventServiceProvider as ServiceProvider; class RepositoryServiceProvider extends ServiceProvider{ public function register(){ //在服務(wù)容器中綁定類 $this->app->bind( 'TrafficTool', 'Train'); $this->app->bind('Traveller', 'Traveller'); } }
實(shí)例化對象
<?php // 實(shí)例化對象 $tra = app()->make('Traveller'); $tra->visitTibet();
當(dāng)我們使用服務(wù)容器獲取旅行類的對象時(shí),容器會自動注入對象所需要的參數(shù)。而在此之前我只需要綁定特定的類就可以了,這樣做才體現(xiàn)了真正的自動化,而且使得旅行類和旅行工具類完全解耦了。當(dāng)我們需要更改旅行方式的時(shí)候,我們就只需要更改綁定就可以了。
總結(jié)
上面舉了幾個(gè)簡單的例子,如果能完全理解和掌握laravel服務(wù)容器,實(shí)際開發(fā)中它會給你提供更多的便利。當(dāng)然它也不是完美無缺的,總之實(shí)際使用中揚(yáng)長避短才是關(guān)鍵。
以上就是詳解Laravel服務(wù)容器的優(yōu)勢的詳細(xì)內(nèi)容,更多關(guān)于Laravel服務(wù)容器的優(yōu)勢的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
php使用Cookie實(shí)現(xiàn)和用戶會話的方法
這篇文章主要介紹了php使用Cookie實(shí)現(xiàn)和用戶會話的方法,分析了Cookie的原理、設(shè)置與使用技巧,需要的朋友可以參考下2015-01-01php打開遠(yuǎn)程文件的方法和風(fēng)險(xiǎn)及解決方法
本文講的是php打開遠(yuǎn)程文件的使用方法,還有使用風(fēng)險(xiǎn)和解決方法2013-11-11PHP中上傳多個(gè)文件的表單設(shè)計(jì)例子
這篇文章主要介紹了PHP中上傳多個(gè)文件的表單設(shè)計(jì)例子,本文著重講解的是表單如何設(shè)計(jì),后端處理需要循環(huán)$_FILES數(shù)組來實(shí)現(xiàn),需要的朋友可以參考下2014-11-11php通過pecl方式安裝擴(kuò)展的實(shí)例講解
下面小編就為大家分享一篇php通過pecl方式安裝擴(kuò)展的實(shí)例講解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-02-02PHP常用特殊運(yùn)算符號和函數(shù)總結(jié)(php新手入門必看)
新手經(jīng)常會有一些PHP特殊符號的問題,這里把常用的特殊符號整理一下。如果你全部都會用,那就當(dāng)是溫故知新吧2013-02-02PHP函數(shù)shuffle()取數(shù)組若干個(gè)隨機(jī)元素的方法分析
這篇文章主要介紹了PHP函數(shù)shuffle()取數(shù)組若干個(gè)隨機(jī)元素的方法,結(jié)合實(shí)例形式詳細(xì)分析了shuffle函數(shù)的功能,定義,使用方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下2016-04-04