《PHP设计模式介绍》第四章 单件模式(2)_PHP教程

编辑Tag赚U币
教程Tag:暂无Tag,欢迎添加,赚取U币!

推荐:《PHP设计模式介绍》第三章 工厂模式
在面向对象编程中, 最通常的方法是一个new操作符产生一个对象实例,new操作符就是用来构造对象实例的。但是在一些情况下, new操作符直接生成对象会带来一些问题。举例来说, 许多类型对象的创造需

下面有个例子,它解释了为什么构造函数保护代码有一个全局的标识:

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]);
}
return $instance[0];
}
}

PHP4允许你改变构造函数中$this的值。在过去,我们会习惯设置 $this = null;当有一个创建构造错误时,确保无效的对象不能被代码继续使用。PHP4中很有用的东西,在PHP5中并不兼容,将来会在你的代码中得到验证,这种技术不再被推荐。

这段代码中另外一个重点是引用操作&的用法。有两种地方需要使用&。第一种是在函数定义时,在函数名字前用来表示将返回一个引用。第二种是将新的DbConn对象赋值给$GLOBALS数组。(在序言和值对象章节中提到过:在PHP4中,你总会使用&操作符,以引用的方式创建、传递和返回对象,)

getInstance()方法的条件检查,常常被写成没有警示的情况下运行,甚至在E_ALL的错误级别下也不会提示。它检查在$GLOBAL数组中适当的位置是否有一个DbConn对象,如果没有,就在那里创建这个对象。这个方法于是返回了这样的结果,这个对象能被重复创建或者这个对象在之前已经被这个方法创建过了。当方法结束时,你可以确认已经拥有这个类的有效实例,而且它已经被有效初始化。

静态方式

关于全局变量的问题,甚至隐藏在getInstance()中的全局变量中也存在。因为全局变量在脚本的任何地方都有效,在没有注意到的情况下,你依然有可能破坏这个全局变量,

在getInstance()方法内部使用静态变量来存储Singleton是一个显得干净的办法。第一个代码片断如下:

class DbConn {
// ...
function &getInstance() {
static $instance = false;
if (!$instance) $instance =& new DbConn(M_E);
return $instance;
}
}

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() {
static $instance = array();
if (!$instance) $instance0 =& new DbConn(M_E);
return $instance0;
}
}

虽然这段代码有点依赖PHP的布尔方式,但它比那个全局版本更严谨:在条件检测时,使用一个空的数组会得到结果false。就像在DbConn类的前一个版本一样,在函数的定义和赋值部分需要引用操作符。

分享:《PHP设计模式介绍》第二章 值对象模式
在所有的最简单的程序中,大多数对象都有一个标识,一个重要的商业应用对象,例如一个Customer或者一个SKU,有一个或者更多的属性---id,name,email地址,这样可以把它从同一个类的其他实例区分开

来源:模板无忧//所属分类:PHP教程/更新时间:2008-08-22
相关PHP教程