上文:《PHP設計模式介紹》第三章 工廠模式
《PHP設計模式介紹》第四章 單條模式
幾乎所有面向?qū)ο蟮某绦蛑,總有一兩個資源被創(chuàng)建出來,在程序應用中持續(xù)被共享使用。例如,這樣的一個資源,在一個電子商務程序的數(shù)據(jù)庫連接中使用:這個連接在應用程序啟動時初始化,程序于是可以有效的執(zhí)行;當程序結束時,這個連接最終被斷開并銷毀。如果是你寫的代碼,沒必要在每時每刻創(chuàng)建一個數(shù)據(jù)庫連接,這樣非常低效。已經(jīng)建立好的連接應該能被你的代碼簡單重復的使用。這個問題就是,基于以上要求你將如何進行這個數(shù)據(jù)庫連接?(或者連接其它被循環(huán)使用的唯一資源,比如一個開放文件或者一個隊列。)
問題
你怎樣確保一個特殊類的實例是獨一無二的(它是這個類的唯一實例),并且它很存取容易呢?
解決方案
當然,全局變量是顯而易見的解決方案。但它就像潘多拉的盒子(正確的判斷來自經(jīng)驗,而錯誤的判斷產(chǎn)生經(jīng)驗。這句諺語就是這個意思。),你的任何代碼都能修改全局變量,這將不可避免的引起更多調(diào)試的意外。換句話說,全局變量的狀態(tài)總是會出現(xiàn)一些問題的,(這里有一個關于全局變量使用問題不錯的描述,http://c2.com/cgi/wiki?GlobalVariablesAreBad)。
當你需要一個特殊類的唯一實例時,使用這個名字叫單件的模式;趩渭J降念惸軐嵗统跏蓟@個類的一個實例,并且提供每時每刻絕對相同的連接。一般情況下使用名為getInstance()的靜態(tài)方法實現(xiàn)。
關鍵問題是,如何在每時每刻獲得一個精確統(tǒng)一的實例。請看下面的例子:
// PHP4 function TestGetInstance() { $this->assertIsA( $obj1 =& DbConn::getInstance(), ‘DbConn’, ‘The returned object is an instance of DbConn’); $this->assertReference( $obj1, $obj2 =& DbConn::getInstance(), ‘Two calls to getInstance() return the same object’); }
注釋:assertReference assertReference() 方法確保兩個被傳遞的參數(shù)引用自相同的PHP變量。 在PHP4中,這里斷言兩個被測試的參數(shù)的卻是相同的對象。assertReference() 這個方法在移植到PHP5以后也許就不推薦使用了。
這個test方法有兩個斷言:第一個判斷第調(diào)用靜態(tài)方法DbConn::getInstance()返回的值是DbConn對象的實例,第二個用來判斷第二次調(diào)用getInstance()方法返回得值引用的是相同的對象實例,這意味著他們使用的是同一個對象。
除了斷言代碼預期的執(zhí)行結果,Test也預示了getInstance()的正確用法(PHP4):$local_conn_var=&DbConn::getInstance()。引用(=&)靜態(tài)方法的返回值賦值給了這個局部變量。
再寫另外一段測試代碼:直接用“new”來實例化一個單件類會引起某些類型的錯誤。test代碼如下:
function TestBadInstantiate() { $obj =& new DbConn; $this->assertErrorPattern( ‘/(bad|nasty|evil|do not|don\’t|warn).*’. ‘(instance|create|new|direct)/i’); }
這段代碼直接創(chuàng)建了一個 DbConn 的實例,將會引起PHP報錯。為了讓代碼更穩(wěn)定,我們用PCRE正則表達式來匹配報錯信息。(顯示報錯信息的確切措詞并不重要。)
出處:phpchina
責任編輯:bluehearts
上一頁 下一頁 php設計模式介紹之單件模式 [2]
◎進入論壇網(wǎng)絡編程版塊參加討論
|