<?php /* Singleton && Registry Design Pattern Implementation */ class Registry { private $_store = array(); public function getInstance() { static $instance = array(); if (!$instance) { $instance[0] = new Registry; } return $instance[0]; } public function &get($key){ if($this->isValid($key)){ return $this->_store[$key]; } } public function set($key, $object){ $this->_store[$key] = &$object; } public function isValid($key){ return array_key_exists($key,$this->_store); } } ?> Test Case: <?php require_once 'simpletest/unit_tester.php'; require_once 'simpletest/reporter.php'; require_once 'Registry.php'; class RegistryTestCase extends UnitTestCase{ function testRegistryIsSingleton(){ $this->assertIsA($reg = Registry::getInstance(), 'Registry'); $this->assertReference($reg, Registry::getInstance()); } function testEmptyRegistryKeyIsReturnNull(){ $reg = Registry::getInstance(); $this->assertNull($reg->get('key')); } function testEmptyRegistryKeyIsInvalid(){ $reg = Registry::getInstance(); $this->assertFalse($reg->get('key')); } function testSetRegistryKeyBecomesValid(){ $reg = Registry::getInstance(); $test_value = 'something'; settype($test_value, 'Object'); $reg->set('key', $test_value); $this->assertTrue($reg->isValid('key')); } function testRegistryValueIsReference(){ $reg = Registry::getInstance(); $test_value = 'something'; $reg->set('key', $test_value); $this->assertReference($test_value, $reg->get('key')); $test_value .= ' else'; $reg->set('key', $test_value); $this->assertEqual('something else', $reg->get('key')); } } if(!defined('RUN_ALL')){ $test = new RegistryTestCase (); $test->run(new HtmlReporter()); //$test->run(new TextReporter()); } ?> 仅仅是缺少一个" &",这就是问题所在^_^,神奇,All Pass,Green Bar,HoHo: <?php /* Singleton && Registry Design Pattern Implementation */ class Registry { private $_store = array(); public function getInstance() { static $instance = array(); if (!$instance) { $instance[0] = new Registry; } return $instance[0]; } public function &get($key){ if($this->isValid($key)){ return $this->_store[$key]; } } public function set($key, &$object){ $this->_store[$key] = &$object; } public function isValid($key){ return array_key_exists($key,$this->_store); } } ?> 使用实例: 数据库连接注册库单件 <?php require_once 'DB.php'; require_once 'simpletest/unit_tester.php'; require_once 'simpletest/reporter.php'; class DatabaseConnectionSingleton { public static function getInstance() { /* 这里$db对象是静态的,对getInstance()的多次调用返回相同的引用,通过下面的TestCase得到了验证 */ static $db = null; if ($db === null) { $db = new DatabaseConnectionSingleton(); } return $db; } private $_handle = null; # 构造方法是私有的,所以不能直接使用 new 关键字实例化,这点对于单件模式至关重要 private function __construct() { $dsn = 'mysql://root:root@localhost/test'; $this->_handle = DB :: connect($dsn, array ()); } public function handle() { return $this->_handle; } } # debug output #print( "Handle = ".DatabaseConnectionSingleton::getInstance()->handle()." " ); #print( "Handle = ".DatabaseConnectionSingleton::getInstance()->handle()." " ); # dump DatabaseConnectionSingleton 对象 #var_dump(DatabaseConnectionSingleton::getInstance()); #print_r(get_included_files()); /** * 验证对getInstance()的多次调用返回相同的引用. */ class DatabaseConnectionSingletonTestCase extends UnitTestCase { function testIsReferceReturnsObjectTwice() { $instance1 = DatabaseConnectionSingleton :: getInstance(); $instance2 = DatabaseConnectionSingleton :: getInstance(); $this->assertReference($instance1, $instance2); } } $test = new DatabaseConnectionSingletonTestCase(); $test->run(new HtmlReporter()); # 下面是单件模式的原型,注意三个要点, # 1. 对象必须是私有成员. # 2.私有的构造函数 # 3. 一个公共的实例化并返回该Singleton的可被外部对象调用的成员函数 # 单件模式的事例化过程被从外部移到了内部.只有通过内部方法才能实例化对象 class Singleton { private static $instance = null; private function __construct() { } public static function getInstance() { if (self :: $instance === null) { self :: $instance = new Singleton(); } return self :: instance; } } ?>