《PHP設(shè)計模式介紹》第四章 單件模式_PHP教程
推薦:《PHP設(shè)計模式介紹》第三章 工廠模式在面向?qū)ο缶幊讨? 最通常的方法是一個new操作符產(chǎn)生一個對象實例,new操作符就是用來構(gòu)造對象實例的。但是在一些情況下, new操作符直接生成對象會帶來一些問題。舉例來說, 許多類型對象的創(chuàng)造需
幾乎所有面向?qū)ο蟮某绦蛑�,總有一兩個資源被創(chuàng)建出來,在程序應(yīng)用中持續(xù)被共享使用。例如,這樣的一個資源,在一個電子商務(wù)程序的數(shù)據(jù)庫連接中使用:這個連接在應(yīng)用程序啟動時初始化,程序于是可以有效的執(zhí)行;當(dāng)程序結(jié)束時,這個連接最終被斷開并銷毀。如果是你寫的代碼,沒必要在每時每刻創(chuàng)建一個數(shù)據(jù)庫連接,這樣非常低效。已經(jīng)建立好的連接應(yīng)該能被你的代碼簡單重復(fù)的使用。這個問題就是,基于以上要求你將如何進(jìn)行這個數(shù)據(jù)庫連接?(或者連接其它被循環(huán)使用的唯一資源,比如一個開放文件或者一個隊列。)
問題
你怎樣確保一個特殊類的實例是獨一無二的(它是這個類的唯一實例),并且它很存取容易呢?
解決方案
當(dāng)然,全局變量是顯而易見的解決方案。但它就像潘多拉的盒子(正確的判斷來自經(jīng)驗,而錯誤的判斷產(chǎn)生經(jīng)驗。這句諺語就是這個意思。),你的任何代碼都能修改全局變量,這將不可避免的引起更多調(diào)試的意外。換句話說,全局變量的狀態(tài)總是會出現(xiàn)一些問題的,(這里有一個關(guān)于全局變量使用問題不錯的描述,http://c2.com/cgi/wiki?GlobalVariablesAreBad)。
當(dāng)你需要一個特殊類的唯一實例時,使用這個名字叫單件的模式�;趩渭J降念惸軐嵗统跏蓟@個類的一個實例,并且提供每時每刻絕對相同的連接。一般情況下使用名為getInstance()的靜態(tài)方法實現(xiàn)。
關(guān)鍵問題是,如何在每時每刻獲得一個精確統(tǒng)一的實例。請看下面的例子:
|
class DbConn { |
注釋:assertReference
assertReference() 方法確保兩個被傳遞的參數(shù)引用自相同的PHP變量。
在PHP4中,這里斷言兩個被測試的參數(shù)的卻是相同的對象。assertReference() 這個方法在移植到PHP5以后也許就不推薦使用了。
這個test方法有兩個斷言:第一個判斷第調(diào)用靜態(tài)方法DbConn::getInstance()返回的值是DbConn對象的實例,第二個用來判斷第二次調(diào)用getInstance()方法返回得值引用的是相同的對象實例,這意味著他們使用的是同一個對象。
除了斷言代碼預(yù)期的執(zhí)行結(jié)果,Test也預(yù)示了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’); } |
樣本代碼
單件模式是一個很有趣的模式。讓我們用PHP4和PHP5兩種方式來探究它的實現(xiàn)過程,現(xiàn)在從PHP4開始。
全局方式
理論上說,一個全局變量可以生成一個完美的單件,但全局變量可能被修改:在代碼運行過程中,不能保證全局變量指向的是一個對象。因而,不讓全局變量在全局直接引用,就可以減少“太隨意訪問”這個全局變量的問題。比如說,這段代碼使用一個非常長而且獨特的名字,從而“隱藏”了全局變量的引用。
| class DbConn { function DbConn($fromGetInstance=false) { if (M_E != $fromGetInstance) { trigger_error(‘The DbConn class is a Singleton,’ .’ please do not instantiate directly.’); } } function &getInstance() { $key = ‘__some_unique_key_for_the_DbConn_instance__’; if (!(array_key_exists($key, $GLOBALS) && is_object($GLOBALS[$key]) && ‘dbconn’ == get_class($GLOBALS[$key]) )) { $GLOBALS[$key] =& new DbConn(M_E); } return $GLOBALS[$key]; } } |
表示成一個UML類圖,解決辦法如下:
如果你不選用這個“神秘參數(shù)”-類型保護(hù),建立一個全局標(biāo)記是另外一個選擇,用它來驗證你是通過getInstance()方法來創(chuàng)建的對象。保護(hù)方式從“你知道它的名字”改變成“它存在于環(huán)境中”。
分享:《PHP設(shè)計模式介紹》第二章 值對象模式在所有的最簡單的程序中,大多數(shù)對象都有一個標(biāo)識,一個重要的商業(yè)應(yīng)用對象,例如一個Customer或者一個SKU,有一個或者更多的屬性---id,name,email地址,這樣可以把它從同一個類的其他實例區(qū)分開
- PHPNOW安裝Memcached擴(kuò)展方法詳解
- php記錄頁面代碼執(zhí)行時間
- PHP中獎概率的抽獎算法程序代碼
- apache設(shè)置靜態(tài)文件緩存方法介紹
- php對圖像的各種處理函數(shù)代碼小結(jié)
- PHP 關(guān)于訪問控制的和運算符優(yōu)先級介紹
- 關(guān)于PHP語言構(gòu)造器介紹
- php/js獲取客戶端mac地址的實現(xiàn)代碼
- php5.5新數(shù)組函數(shù)array_column使用
- PHP preg_match的匹配多國語言的技巧
- php 中序列化和json使用介紹
- php采集文章中的圖片獲取替換到本地
PHP教程Rss訂閱編程教程搜索
PHP教程推薦
- php實現(xiàn)單鏈表的實例代碼
- 關(guān)于二級目錄拖拽排序的實現(xiàn)(源碼示例下載)
- 讓你的PHP引擎全速運轉(zhuǎn)的三個簡單絕招
- setcookie中Cannot modify header information-headers already sent by錯誤的解決方法詳解
- PHP數(shù)據(jù)庫備份類
- PHP技巧:優(yōu)化動態(tài)網(wǎng)頁技術(shù)PHP程序的12條技巧
- ajax完美實現(xiàn)兩個網(wǎng)頁 分頁功能的實例代碼
- php實現(xiàn)gb2312和unicode間編碼轉(zhuǎn)換
- php自動識別文字字符串編碼并轉(zhuǎn)為目標(biāo)編碼
- 創(chuàng)建XML Http Request對象兩個的方法
- 相關(guān)鏈接:
- 教程說明:
PHP教程-《PHP設(shè)計模式介紹》第四章 單件模式
。