PHP注册模式用于存储一些公共资源,比如数据库连接,全局对象,通常Registry实现为一个单件模式,它本身就是一个单件.我在编写Registry对象的时候犯了一个错误,就是在实现set方法的时候没有pass by reference,所有没有通过simpletest的test case.睡了一觉,第二天脑子似乎清醒了一些.发现在实现set的时候没有通过 & 传递对象.下面是我没有通过test case的Registry实现代码:
<?
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);
}
}
?>
/*
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:












































仅仅是缺少一个" &",这就是问题所在^_^,神奇,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);
}
}
?>
/*
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;
}
}
?>
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;
}
}
?>