#phalapi-進階篇2(DI依賴注入和單例模式)#php
##前言## 先在這裏感謝phalapi框架創始人@dogstar,爲咱們提供了這樣一個優秀的開源框架.java
離上一次更新過去了快兩週,在其中編寫了一個關於DB分表分庫解決大數據量的拓展,有興趣的童鞋能夠了解了解.廢話很少說,本小節在於解釋一下在PhalApi框架中兩個比較好的思想,單例模式和依賴注入.git
附上:web
官網地址:http://www.phalapi.net/spring
開源中國Git地址:http://git.oschina.net/dogstar/PhalApi/tree/release編程
##1. 單例模式##設計模式
單例模式對於長期進行過面向對象編程的童鞋應該不算陌生,在學習php的童鞋也應該有聽過,這裏簡單的聊一聊單例模式究竟是一個怎麼樣東西,解決了什麼問題,而且在PhalApi中是如何實現的.api
單例單例,所謂單例也就是有且只有一個存在,這就是單例,不難看出他的好處資源利用少由於只有一個,你們都是知道要使用一個類必需要實例他也就是new在每次new一個對象的時候都會在內存中生成一塊區域來存放這個實例,若是在程序一次運行中使用了不少的new實例化了同一個對象,那就比較消耗資源了,可是若是是通用一個使用全局變量global程序又會顯得不優雅並且會很亂,在這種狀況下單例模式就產生了.數組
單例模式就是一個一箭雙鵰的一個方法既能夠全局通用,二不用擔憂佔用過多的資源,三又很是優雅,咱們來一塊兒看看在PhalApi中是如何實現單例模式的:框架
//你們看到咱們經常使用的DI方法內部實現的是PhalApi_DI中的靜態方法one方法 function DI() { return PhalApi_DI::one(); }
而後咱們看向one方法內部
每當咱們請求過來的時候先驗證靜態變量instance是否是沒有被初始化,若是是第一次調用他會在內部去實例化PhalApi_DI類而後負值給**$instance**而後返回實例好的這個靜態變量,當咱們下次在請求過來的時候這個靜態變量已經被實例化好了就會直接跳過實例的過程直接返回這個對象,也就是咱們在PhalApi框架全部的地方使用的DI方法其實都是一個對象,在內存中只存在一塊區域,代碼以下:
public static function one(){ if(self::$instance == NULL){ self::$instance = new PhalApi_DI(); self::$instance->onConstruct(); } return self::$instance; }
其實不難咱們只用吧new一個類的操做封裝到咱們須要new的類的靜態方法在向上面同樣的去判斷,就能夠很簡單的去實現單例模式.
##2. 依賴注入##
依賴注入又稱之爲**"控制反轉",若是是熟悉javaweb開發的spring**框架應該有比較深的感觸,在這裏也不往深的講,就簡單講解一下PhalApi中DI依賴注入的實現讓你們瞭解這種設計模式如何實現以及自此基礎上實現的惰性加載機制.
###2.1 DI依賴注入實現###
你們在PhalApi中經常使用的DI()方法,也就是採用咱們上面所謂的單例模式不用多說了,也就是咱們每次使用DI()其實就是在使用PhalApi_DI類,那麼咱們依賴注入的關鍵也就是在PhalApi_DI之中
先來說一下他的一個實現方式在來說具體實現,這裏舉個例子:
//配置 DI()->config = new PhalApi_Config_File(API_ROOT . '/Config');
其實在內部有一個數組,它吧config做爲了key,吧new PhalApi_Config_File(API_ROOT . '/Config')做爲了value而後保存了起來當咱們下一次使用DI->config->get();的時候它就會根據key值config拿出開始new好的類,因此能夠說config操做是依賴於DI(),並且在使用DI()->config的時候永遠都是在使用的一個實例,也能減小資源的消耗.
有的童鞋就好奇了爲何DI()->config會存到數組須要的時候會拿出來呢,感興趣的童鞋能夠百度一下魔法方法**__ser和__get**
/**你們能夠看到這是PhalApi_DI中的魔法方法__set * 也就是當使用DI()->config = new PhalApi_Config_File(API_ROOT . '/Config');的時候 * 得到的name值就是config,得到的value也就是new PhalApi_Config_File(API_ROOT . '/Config'); */get同理,在內部實現都是調用了內部get和set方法 public function __set($name, $value){ $this->set($name, $value); } public function __get($name){ return $this->get($name, NULL); }
看完以後你們是否是以爲很簡單啊,你們之後也能夠在本身設計類的時候採用這種靈活的魔法方法實現.
###2.2 惰性加載###
在PhalApi中的DI()方法也提供惰性加載,惰性加載如字意也就是當類沒有被使用到的時候不會加載,這樣的操做也是爲了不浪費沒必要要的資源,當咱們不是用的時候永遠不會去實例化只有當你使用到的時候纔會去new這個類而後實例化以後使用,咱們來看看是如何實現的.
//當咱們執行如下語句的時候,在依賴注入的時候存的是value值是字符串的test DI()->test = 'test'; //使用DI()->test->test();的時候會使用到PhalApi中的get方法,在get方法中有一段代碼 $this->data[$key] = $this->initService($this->data[$key]); //在initService方法內部驗證了value是字符串就實例化了再返回 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; }
##3. 總結##
在本節中簡單的講解了關於單例模式,依賴注入以及惰性加載,這幾種設計模式都是經常使用的能後減小資源利用率的有效的方法,但願你們看了這篇介紹可以實地的去體驗一下PhalApi中的這幾種模式,在下一小節就講解如何構建本身的攔截器,但願你們可以持續關注!
注:筆者能力有限有說的不對的地方但願你們可以指出,也但願多多交流!
官網QQ交流羣:421032344 歡迎你們的加入!