国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > PHP > 正文

《PHP設計模式介紹》第四章 單件模式

2024-05-04 21:51:46
字體:
來源:轉載
供稿:網友

幾乎所有面向對象的程序中,總有一兩個資源被創建出來,在程序應用中持續被共享使用。例如,這樣的一個資源,在一個電子商務程序的數據庫連接中使用:這個連接在應用程序啟動時初始化,程序于是可以有效的執行;當程序結束時,這個連接最終被斷開并銷毀。如果是你寫的代碼,沒必要在每時每刻創建一個數據庫連接,這樣非常低效。已經建立好的連接應該能被你的代碼簡單重復的使用。這個問題就是,基于以上要求你將如何進行這個數據庫連接?(或者連接其它被循環使用的唯一資源,比如一個開放文件或者一個隊列。)

問題

你怎樣確保一個特殊類的實例是獨一無二的(它是這個類的唯一實例),并且它很存取容易呢?

解決方案

當然,全局變量是顯而易見的解決方案。但它就像潘多拉的盒子(正確的判斷來自經驗,而錯誤的判斷產生經驗。這句諺語就是這個意思。),你的任何代碼都能修改全局變量,這將不可避免的引起更多調試的意外。換句話說,全局變量的狀態總是會出現一些問題的,(這里有一個關于全局變量使用問題不錯的描述,http://c2.com/cgi/wiki?GlobalVariablesAreBad)。

當你需要一個特殊類的唯一實例時,使用這個名字叫單件的模式。基于單件模式的類能實例化和初始化這個類的一個實例,并且提供每時每刻絕對相同的連接。一般情況下使用名為getInstance()的靜態方法實現。

關鍵問題是,如何在每時每刻獲得一個精確統一的實例。請看下面的例子:

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];
}
}

注釋:assertReference

assertReference() 方法確保兩個被傳遞的參數引用自相同的PHP變量。

在PHP4中,這里斷言兩個被測試的參數的卻是相同的對象。assertReference() 這個方法在移植到PHP5以后也許就不推薦使用了。

這個test方法有兩個斷言:第一個判斷第調用靜態方法DbConn::getInstance()返回的值是DbConn對象的實例,第二個用來判斷第二次調用getInstance()方法返回得值引用的是相同的對象實例,這意味著他們使用的是同一個對象。

除了斷言代碼預期的執行結果,Test也預示了getInstance()的正確用法(PHP4):$local_conn_var=&DbConn::getInstance()。引用(=&)靜態方法的返回值賦值給了這個局部變量。

再寫另外一段測試代碼:直接用“new”來實例化一個單件類會引起某些類型的錯誤。test代碼如下:

function TestBadInstantiate() {
$obj =& new DbConn;
$this->assertErrorPattern(
/(bad|nasty|evil|do not|don/t|warn).*.
(instance|create|new|direct)/i);
}

樣本代碼

單件模式是一個很有趣的模式。讓我們用PHP4和PHP5兩種方式來探究它的實現過程,現在從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類圖,解決辦法如下:

如果你不選用這個“神秘參數”-類型保護,建立一個全局標記是另外一個選擇,用它來驗證你是通過getInstance()方法來創建的對象。保護方式從“你知道它的名字”改變成“它存在于環境中”。

共3頁上一頁123下一頁
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 长丰县| 鄂尔多斯市| 韶山市| 兴安县| 大同市| 桃园市| 连江县| 南华县| 嘉善县| 云安县| 奎屯市| 同江市| 嵊州市| 兰坪| 板桥市| 桦南县| 贞丰县| 搜索| 福泉市| 保靖县| 三台县| 安达市| 濉溪县| 玉林市| 洞口县| 来宾市| 始兴县| 彰化县| 读书| 佛教| 恩施市| 庆安县| 墨脱县| 凤凰县| 安泽县| 贺兰县| 乾安县| 长阳| 伊宁县| 石家庄市| 迁安市|