W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
先在這里感謝phalapi框架創(chuàng)始人@dogstar,為我們提供了這樣一個(gè)優(yōu)秀的開(kāi)源框架.
離上一次更新過(guò)去了快兩周,在其中編寫(xiě)了一個(gè)關(guān)于DB分表分庫(kù)解決大數(shù)據(jù)量的拓展,有興趣的童鞋可以了解了解.廢話不多說(shuō),本小節(jié)在于解釋一下在PhalApi框架中兩個(gè)比較好的思想,單例模式和依賴注入.
附上:
喵了個(gè)咪的博客:w-blog.cn
官網(wǎng)地址:http://www.phalapi.net/
開(kāi)源中國(guó)Git地址:http://git.oschina.net/dogstar/PhalApi/tree/release
單例模式對(duì)于長(zhǎng)期進(jìn)行過(guò)面向?qū)ο缶幊痰耐瑧?yīng)該不算陌生,對(duì)學(xué)習(xí)php的童鞋也應(yīng)該有聽(tīng)過(guò),這里簡(jiǎn)單的聊一聊單例模式它到底是一個(gè)怎么樣的東東,解決了怎么樣的問(wèn)題,并且在PhalApi中它是如何實(shí)現(xiàn)的.
單例單例,所謂單例也就是保證一個(gè)類僅有一個(gè)實(shí)例,并提供一個(gè)訪問(wèn)它的全局訪問(wèn)點(diǎn),這就是單例,不難看出他的好處:資源利用少,因?yàn)橹挥幸粋€(gè),大家都是知道要使用一個(gè)類必須要實(shí)例他,也就是new,在每次new一個(gè)對(duì)象的時(shí)候都會(huì)在內(nèi)存中生成一塊區(qū)域來(lái)存放這個(gè)實(shí)例,如果在程序一次運(yùn)行中使用了很多的new實(shí)例化了同一個(gè)對(duì)象,那就比較消耗資源了,但是如果是通用一個(gè)使用全局變量global程序又會(huì)顯得不那么優(yōu)雅而且會(huì)很亂,在這種情況下,單例模式就產(chǎn)生了.
單例模式是一個(gè)很好的解決方案,既可以全局通用,又不必?fù)?dān)心占用過(guò)多的資源,且非常優(yōu)雅。我們來(lái)一起看看在PhalApi中是如何實(shí)現(xiàn)單例模式的:
//大家看到我們常用的DI方法內(nèi)部實(shí)現(xiàn)的是PhalApi_DI中的靜態(tài)方法one方法
function DI() {
return PhalApi_DI::one();
}
然后我們看向one方法內(nèi)部
每當(dāng)請(qǐng)求過(guò)來(lái)時(shí)先驗(yàn)證靜態(tài)變量instance是否已被類初始化賦值,若無(wú),則會(huì)在內(nèi)部去實(shí)例化PhalApi_DI類,然后賦值給$instance并返回,若有,則當(dāng)下次請(qǐng)求過(guò)來(lái)時(shí),直接返回已實(shí)例化的對(duì)象。簡(jiǎn)言之,PhalApi框架所有的地方使用的DI方法,其實(shí)都是返回同一個(gè)對(duì)象實(shí)例,在內(nèi)存中只存在一塊區(qū)域,代碼如下:
public static function one(){
if(self::$instance == NULL){
self::$instance = new PhalApi_DI();
self::$instance->onConstruct();
}
return self::$instance;
}
依賴注入又稱之為"控制反轉(zhuǎn)",如果是熟悉javaweb開(kāi)發(fā)的spring框架應(yīng)該有比較深的感觸,在這里也不往深的講,就簡(jiǎn)單講解一下PhalApi中DI依賴注入的實(shí)現(xiàn),以便讓大家了解這種設(shè)計(jì)模式實(shí)現(xiàn)原理以及自此基礎(chǔ)上實(shí)現(xiàn)的惰性加載機(jī)制.
大家在PhalApi中常用的DI()方法,也就是采用我們上面所謂的單例模式,我們每次使用DI()就是在使用PhalApi_DI類,其實(shí)我們依賴注入的關(guān)鍵也就是在PhalApi_DI之中
先來(lái)講一下他的一個(gè)實(shí)現(xiàn)方式再來(lái)講具體實(shí)現(xiàn),這里舉個(gè)例子:
//配置
DI()->config = new PhalApi_Config_File(API_ROOT . '/Config');
其實(shí)在內(nèi)部有一個(gè)數(shù)組,它把config作為了key,把new PhalApi_Config_File(API_ROOT . '/Config')作為了value,然后保存了起來(lái)。當(dāng)我們下一次使用DI->config->get()的時(shí)候,它就會(huì)根據(jù)key值config拿出開(kāi)始new好的類,所以可以說(shuō)config操作是依賴于DI(),而且在使用DI()->config的時(shí)候永遠(yuǎn)都是在使用同一個(gè)實(shí)例,減少資源的消耗.
有的童鞋就好奇了為什么DI()->config會(huì)存到數(shù)組里而在需要的時(shí)候會(huì)拿出來(lái)?感興趣的童鞋可以百度一下魔法方法set和get
/**大家可以看到這是PhalApi_DI中的魔法方法__set
* 也就是當(dāng)使用DI()->config = new PhalApi_Config_File(API_ROOT . '/Config');的時(shí)候
* 獲得的name值就是config,獲得的value也就是new PhalApi_Config_File(API_ROOT . '/Config');
*/get同理,在內(nèi)部實(shí)現(xiàn)都是調(diào)用了內(nèi)部get和set方法
public function __set($name, $value){
$this->set($name, $value);
}
public function __get($name){
return $this->get($name, NULL);
}
看完之后大家是不是覺(jué)得很簡(jiǎn)單啊,大家以后也可以在設(shè)計(jì)自己的類的時(shí)候采用這種靈活的魔法方法實(shí)現(xiàn).
在PhalApi中的DI()方法也提供惰性加載,惰性加載如字意也就是當(dāng)類沒(méi)有被使用到的時(shí)候不會(huì)被加載,這樣的操作也是為了避免浪費(fèi)不必要的資源,當(dāng)我們不使用的時(shí)候永遠(yuǎn)不會(huì)去實(shí)例化,只有當(dāng)你使用到的時(shí)候才會(huì)去實(shí)例化。接下來(lái),我們來(lái)看看是如何實(shí)現(xiàn)的.
//當(dāng)我們執(zhí)行以下語(yǔ)句的時(shí)候,在依賴注入的時(shí)候存的是value值是字符串的test
DI()->test = 'test';
//使用DI()->test->test();的時(shí)候會(huì)使用到PhalApi中的get方法,在get方法中有一段代碼
$this->data[$key] = $this->initService($this->data[$key]);
//在initService方法內(nèi)部驗(yàn)證了value是字符串就實(shí)例化了再返回
if($config instanceOf Closure){
$rs = $config();
}elseif(is_string($config) && class_exists($config)){
$rs = new $config();
if(is_callable(array($rs, 'onInitialize'))){
call_user_func(array($rs, 'onInitialize'));
}
}else{
$rs = $config;
}
在本節(jié)中簡(jiǎn)單的講解了關(guān)于單例模式,依賴注入以及惰性加載,這幾種設(shè)計(jì)模式都是常用的,能夠減少資源利用率,希望大家看了這篇介紹能夠親自地去體驗(yàn)一下PhalApi中的這幾種模式。在下一小節(jié)就講解如何構(gòu)建自己的攔截器,希望大家能夠繼續(xù)關(guān)注!
注:筆者能力有限,有說(shuō)的不對(duì)的地方,希望大家能夠指出,也希望多多交流!
官網(wǎng)QQ交流群:421032344 歡迎大家的加入!
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: