php教程:php设计模式介绍之注册模式(5)

http://www.itjxue.com  2015-07-17 08:20  来源:未知  点击次数: 

将注册模式实现为单件模式:

如前所述,把注册模式实现为单件模式有很多实现方式。

第一步,将注册模式实现为单件对象,(作者注:我们在第四章——The Singleton Pattern末尾简单讨论过)。

按照这种设计,注册模式类的任何一个实例都将访问同一个数组。我们把这个新类叫做RegistryGlobal以区别于我们前面开发的类,并反映这种实现方式的特性。

以下为反映这种思想的测试用例(它应该看起来很熟悉)。

代码:

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()方法与我们前面开发的注册模式类完全相同。

下一步:我们来编写验证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'));
}
}

这里测试用例创建了RegistryGlobal类的两个实例,并确认他们不是对同一对象的引用——在一个实例内设置一个对象的属性值(value),最后证实两个实例返回相同的对象。若测试通过RegistryGlobal类就拥有单态的行为。

代码:

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支持这一特性的话,静态类变量会是更好的解决方案。然而,我们可以在代码中通过引用实现静态类变量吗?

测试与 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’));
}

}

要自己实现类静态变量,可以将一个对函数静态变量的引用绑定到类的实例变量上。

代码:

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()方法包含一个初始化为数组的静态变量。这个静态变量通过引用返回。在构造函数中$_store实例变量被赋于通过initRegistry()函数返回的引用——即静态数组。好!一个PHP4的类静态变量产生了。

(责任编辑:IT教学网)

更多