樣本代碼
單件模式是一個很有趣的模式。讓我們用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]; } }
在DbConn的構(gòu)造函數(shù)中,你可能對$fromGetInstance的默認參數(shù)感到疑惑。在對象被直接實例化時,它能夠提供(很微弱的)保護:除非這個默認值變成e (在PHP的數(shù)學常量中 M_E = 2.718281828459),否則這段代碼會報錯。
表示成一個UML類圖,解決辦法如下:
如果你不選用這個“神秘參數(shù)”-類型保護,建立一個全局標記是另外一個選擇,用它來驗證你是通過getInstance()方法來創(chuàng)建的對象。保護方式從“你知道它的名字”改變成“它存在于環(huán)境中”。
下面有個例子,它解釋了為什么構(gòu)造函數(shù)保護代碼有一個全局的標識:
class DbConn { function DbConn() { $token = ‘__some_DbConn_instance_create_semaphore__’; if (!array_key_exists($token, $GLOBALS)) { trigger_error(‘The DbConn class is a Singleton,’ .’ please do not instantiate directly.’); } } function &getInstance() { static $instance = array(); if (!$instance) { $token = ‘__some_DbConn_instance_create_semaphore__’; $GLOBALS[$token] = true; $instance[0] =& new DbConn; unset($GLOBALS[$token]); }
提示
PHP4允許你改變構(gòu)造函數(shù)中$this的值。在過去,我們會習慣設置 $this = null;當有一個創(chuàng)建構(gòu)造錯誤時,確保無效的對象不能被代碼繼續(xù)使用。PHP4中很有用的東西,在PHP5中并不兼容,將來會在你的代碼中得到驗證,這種技術不再被推薦。
這段代碼中另外一個重點是引用操作&的用法。有兩種地方需要使用&。第一種是在函數(shù)定義時,在函數(shù)名字前用來表示將返回一個引用。第二種是將新的DbConn對象賦值給$GLOBALS數(shù)組。(在序言和值對象章節(jié)中提到過:在PHP4中,你總會使用&操作符,以引用的方式創(chuàng)建、傳遞和返回對象,)
getInstance()方法的條件檢查,常常被寫成沒有警示的情況下運行,甚至在E_ALL的錯誤級別下也不會提示。它檢查在$GLOBAL數(shù)組中適當?shù)奈恢檬欠裼幸粋DbConn對象,如果沒有,就在那里創(chuàng)建這個對象。這個方法于是返回了這樣的結(jié)果,這個對象能被重復創(chuàng)建或者這個對象在之前已經(jīng)被這個方法創(chuàng)建過了。當方法結(jié)束時,你可以確認已經(jīng)擁有這個類的有效實例,而且它已經(jīng)被有效初始化。
出處:phpchina
責任編輯:bluehearts
上一頁 php設計模式介紹之單件模式 [1] 下一頁 php設計模式介紹之單件模式 [3]
◎進入論壇網(wǎng)絡編程版塊參加討論
|