當PHP5的出現面向對象思想,我們在構造PHP程序時候就有了對程序的新的總結,把對象特性封裝到類,特別是當PHP框架應用到實際項目中,構造類的對象和調用類對像出現了很大的講究。
我們很多時候會發現,我們在寫一些程序的時候,期望只要第一次構造了該對象,以後操作就是直接對該對象進行其他動作的操作,其實,每個類在構造一個對象後都是可以實現物件對方法或屬性的調用,這是物件導向最基本的做法。但如果你研究了一些框架集合後,特別是應用到MVC模式下的框架開發程序,你會發現一個Controller裡面會有很多個action,也就是我們所說的控制器裡的方法有很多,當然你也會發現當一個控制器控制一個事務對像操作的時候,裡面會出現很多次構造對象,操作資料集合的動作,但是你也會發現如果每次都是靠NEW方式去構造對象的話,無疑就是一次次給自己的記憶體空間增加負擔。因為構造一個新的對象無疑就是要分配一個新的內存空間給它,但是如果你其實只是要求同一個對象動作的延續,那麼試圖尋找已經構造好的對象,並調用它無疑是個很不錯的想法。所謂,同一物件的動作的延續,這個問題其實也很好解釋,例如我現在建構一個控制器類別為Controller A,裡面是對資料Model A的一個添加,刪除等操作,那麼我們的控制動作就會存在假設為action Add ,actionDelete ,按照常規,我們通常利用框架集的單點入口原理,透過路由分配器程式找到了Controller A,但是裡面會如果要單獨調用actionAdd或,actionDelete ,且兩個動作都是對Model A進行的資料操作,每次操作依照常規都必須建構資料對象,然後呼叫SQL去執行資料庫操作,假設建構兩個動作都要去操作同一個資料對象時候調用的方法時候都是在使用同一個語句$a=new A()這種形式的話,兩次操作其實就產生了兩個對象,也就同時佔用兩倍的內存空間,試想不過就是要求同一個人去實施兩個動作,有必要兩個人分別去做兩件事情麼,顯然這種條件下是等於資源浪費,而且當動作多了的時候就會出現大量對象資源佔用內存嚴重導致系統性能下降,最終嚴重的就導致崩潰。
其實,我們在寫很多程式的時候也都一再強調,技術完成功能只是最基礎的一部分,一個好的程序或是網站,要研究的不僅僅是功能問題,更重要的是整體性能,特別是對於大型講究效用的程式來說效能是非常重要的。這點上框架集合是非常不錯的典範,它們善於合理使用地址引用。讓如果能一個物件處理的事情,就讓一個物件來處理,把足夠的空間留給其他不同的類別的物件。
框架集合解決對象資源是否重用的最好的方法就是全局變量的使用,當你的對象建立存在的時候,一般是第一次建立時候,就把它裝載到全局變量中,我們也可以叫做註冊對象,所以以後考慮對象呼叫方法的時候就直接去Check全域變數中是該類對象,也就是說看其是否註冊了該對象,如果存在就直接返回該類對象,並告知地址,以便引用。這樣以來是很容易實現物件位址引用的。當建立所有物件變數指向同一記憶體空間的時候,我們說此刻他們只是名字不同,實際上是同一物件。
於是,我們可以建立了這樣的程序代碼如下:
<?php $GLOBALS['objects']['classname']=null; //是否注册类,类名变量 $GLOBALS['objects']['obj']=null; //对象变量 function & getSingle($classname){ if($GLOBALS['objects']['classname']==$classname){ return $GLOBALS['objects']['obj']; }else { $object= new $classname(); $GLOBALS['objects']['classname']=$classname; $GLOBALS['objects']['obj']=&$object; return $GLOBALS['objects']['obj']; } } class Test{ var $p1; function Test(){ $this->p1=1; } function add() { $this->p1++; } function show() { return $this->p1; } } $test1=&getSingle('Test'); $test1->add(); $test2=&getSingle('Test'); echo $test2->show(); $test2->add(); $test3=&getSingle('Test'); echo $test3->show(); if($test1===$test2) echo 'yes'; else echo 'no'; ?>
根據第一次建立對象後,第二次調用讀取數據時候的必然是以原對象為基礎的再操作,可以由後面的程序看到$test2去資料時候結果是2,然後進行add操作後,由$test3再讀取時候發現結果為3顯然是因為動作2完成的效果。由此,我們看到了利用同一物件進行逐步操作的好處所在,在這裡是因為我們將程式碼放在了一起,當然我們在使用框架的使用經常會出現這樣的情況就是將上面的$test1,$ test2,$test3以及他們的動作分別放在同一個控制器的不同動作action中,因為動作塊是相互獨立的,因此,三個對象變量誰先誰後觸發最早建立這個對象內存空間都是隨機而定的。第一次先是偵測全域變數中是否註冊了該對象,並檢查對象位址是否儲存在全域變數中,以後就是對該對象位址進行比對和存取。