將注冊模式實現為單件模式:
如前所述,把注冊模式實現為單件模式有很多實現方式。
第一步,將注冊模式實現為單件對象,(作者注:我們在第四章——The Singleton Pattern末尾簡單討論過)。
按照這種設計,注冊模式類的任何一個實例都將訪問同一個數組。我們把這個新類叫做RegistryGlobal以區(qū)別于我們前面開發(fā)的類,并反映這種實現方式的特性。
以下為反映這種思想的測試用例(它應該看起來很熟悉)。
代碼:
class RegistryGlobalPHP4TestCase extends UnitTestCase { function testRegistryGlobal() { $reg =& new RegistryGlobal; $this->assertFalse($reg->isValid('key')); $this->assertNull($reg->get('key')); $test_value = 'something'; $reg->set('key', $test_value); $this->assertReference($test_value, $reg->get('key')); } }
實現代碼如下所示:
class RegistryGlobal { var $_store = array(); function isValid($key) { return array_key_exists($key, $this->_store); } function &get($key) { if (array_key_exists($key, $this->_store)) return $this->_store[$key]; } function set($key, &$obj) { $this->_store[$key] =& $obj; } }
isValid(), get(),和set()方法與我們前面開發(fā)的注冊模式類完全相同。
下一步:我們來編寫驗證RegistryGlobal類是單件模式的測試用例。
代碼:
class RegistryGlobalPHP4TestCase extends UnitTestCase { function testRegistryGlobal() { /*...*/ } function testRegistryGlobalIsMonoState() { $reg =& new RegistryGlobal; $reg2 =& new RegistryGlobal; $this->assertCopy($reg, $reg2); $test_value = 'something'; $reg->set('test', $test_value); $this->assertReference( $reg->get('test') ,$reg2->get('test')); } }
這里測試用例創(chuàng)建了RegistryGlobal類的兩個實例,并確認他們不是對同一對象的引用——在一個實例內設置一個對象的屬性值(value),最后證實兩個實例返回相同的對象。若測試通過RegistryGlobal類就擁有單態(tài)的行為。
代碼:
define('REGISTRY_GLOBAL_STORE', '__registry_global_store_key__'); class RegistryGlobal {var $_store; function RegistryGlobal() {if (!array_key_exists(REGISTRY_GLOBAL_STORE, $GLOBALS)||!is_array($GLOBALS[REGISTRY_GLOBAL_STORE])) {$GLOBALS[REGISTRY_GLOBAL_STORE] = array(); } $this->_store =& $GLOBALS[REGISTRY_GLOBAL_STORE]; } function isValid($key) {return array_key_exists($key, $this->_store);} function &get($key) {if (array_key_exists($key, $this->_store)) return $this->_store[$key];} function set($key, &$obj) { $this->_store[$key] =& $obj; } }
本方法中的神奇之處在于$this->_store =& $GLOBALS[REGISTRY_GLOBAL_STORE;] 這一行,引用操作符將全局數組綁定到實例變量$_store上。這是單件模式實現的關鍵所在:每次在對象中使用$this->_store變量時,作用反映到全局變量中。
但是并不推薦基于全局變量的解決方案。如果PHP4支持這一特性的話,靜態(tài)類變量會是更好的解決方案。然而,我們可以在代碼中通過引用實現靜態(tài)類變量嗎?
測試與 RegistryGlobal 類的測試相似。
代碼:
class RegistryMonoStatePHP4TestCase extends UnitTestCase { function testRegistryMonoState() { $this->assertCopy( $reg =& new RegistryMonoState; $reg2 =& new RegistryMonoState); $this->assertFalse($reg->isValid(‘key’)); $this->assertNull($reg->get(‘key’)); $test_value = ‘something’; $reg->set(‘key’, $test_value); $this->assertReference($reg->get(‘key’), $reg2->get(‘key’)); } }
要自己實現類靜態(tài)變量,可以將一個對函數靜態(tài)變量的引用綁定到類的實例變量上。
代碼:
class RegistryMonoState {var $_store; function &_initRegistry() { static $store = array(); return $store; } function RegistryMonoState() { $this->_store =& $this->_initRegistry(); } function isValid($key) { return array_key_exists($key, $this->_store); } function &get($key) { if (array_key_exists($key, $this->_store)) return $this->_store[$key]; } function set($key, &$obj) { $this->_store[$key] =& $obj; } }
initRegistry()方法包含一個初始化為數組的靜態(tài)變量。這個靜態(tài)變量通過引用返回。在構造函數中$_store實例變量被賦于通過initRegistry()函數返回的引用——即靜態(tài)數組。好!一個PHP4的類靜態(tài)變量產生了。
出處:phpchina
責任編輯:bluehearts
上一頁 php設計模式介紹之注冊模式 [4] 下一頁 php設計模式介紹之注冊模式 [6]
◎進入論壇網絡編程版塊參加討論
|