万象娱乐的服务? 这个问题就是

By 董德晨

  万象娱乐的服务? 这个问题就是
  jpg” alt=”PHP系列教程:设计模式介绍Ⅳ单件模式” />,

再写另外一段测试代码:直接用“new”来实例化一个单件类会引起某些类型的错误,getInstance方法如下:。
  

万象娱乐的服务?

万象娱乐旗下的万象城娱乐博彩与澳门万象城娱乐,则为宾客提供实时电子博彩玩乐体验。史利骥亲身经历告诉我们:有一种宾 至如归的亲切友好的印象和感觉。有别于比赛的娱乐活动,是为了满足赌客对输赢的需求而开设的活动。您如果要了解更多万象娱乐的服务?请查看awc999.com万象城
  PHP系列教程:设计模式介绍Ⅳ单件模式
  

上一节:《PHP设计模式介绍》第三章 工厂模式
  

《PHP设计模式介绍》第四章 单件模式
  

几乎所有面向对象的程序中,总有一两个资源被创建出来,在程序应用中持续被共享使用。例如,这样的一个资源,在一个电子商务程序的数据库连接中使用:这个连接在应用程序启动时初始化,程序于是可以有效的执行;当程序结束时,这个连接最终被断开并销毁。如果是你写的代码,没必要在每时每刻创建一个数据库连接,这样非常低效。已经建立好的连接应该能被你的代码简单重复的使用。这个问题就是,基于以上要求你将如何进行这个数据库连接?
  

你怎样确保一个特殊类的实例是独一无二的,并且它很存取容易呢?
  

当然,全局变量是显而易见的解决方案。但它就像潘多拉的盒子,你的任何代码都能修改全局变量,这将不可避免的引起更多调试的意外。换句话说,全局变量的状态总是会出现一些问题的,。
  

当你需要一个特殊类的唯一实例时,使用这个名字叫单件的模式。基于单件模式的类能实例化和初始化这个类的一个实例,并且提供每时每刻绝对相同的连接。一般情况下使用名为getInstance的静态方法实现。
  

关键问题是,如何在每时每刻获得一个精确统一的实例。请看下面的例子:
  // PHP4
function TestGetInstance {
$this->assertIsA,
‘DbConn’,
‘The returned object is an instance of DbConn’);
$this->assertReference,
‘Two calls to getInstance return the same object’);
}
  

注释:assertReference
assertReference 方法确保两个被传递的参数引用自相同的PHP变量。
在PHP4中,这里断言两个被测试的参数的却是相同的对象。assertReference 这个方法在移植到PHP5以后也许就不推荐使用了。
  

这个test方法有两个断言:第一个判断第调用静态方法DbConn::getInstance返回的值是DbConn对象的实例,第二个用来判断第二次调用getInstance方法返回得值引用的是相同的对象实例,这意味着他们使用的是同一个对象。
  

除了断言代码预期的执行结果,Test也预示了getInstance的正确用法:$local_conn_var=&DbConn::getInstance。引用静态方法的返回值赋值给了这个局部变量。
  

再写另外一段测试代码:直接用“new”来实例化一个单件类会引起某些类型的错误。test代码如下:
  function TestBadInstantiate {
$obj =& new DbConn;
$this->*’.
‘/i’);
}
  

这段代码直接创建了一个 DbConn 的实例,将会引起PHP报错。为了让代码更稳定,我们用PCRE正则表达式来匹配报错信息。
  

单件模式是一个很有趣的模式。让我们用PHP4和PHP5两种方式来探究它的实现过程,现在从PHP4开始。
  

理论上说,一个全局变量可以生成一个完美的单件,但全局变量可能被修改:在代码运行过程中,不能保证全局变量指向的是一个对象。因而,不让全局变量在全局直接引用,就可以减少“太随意访问”这个全局变量的问题。比如说,这段代码使用一个非常长而且独特的名字,从而“隐藏” 了全局变量的引用。
  class DbConn {
function DbConn {
if {
trigger_error;
}
}
function &getInstance {
$key = ‘__some_unique_key_for_the_DbConn_instance__’;
if && is_object
&& ‘dbconn’ == get_class )) {
$GLOBALS =& new DbConn;
}
return $GLOBALS;
}
}
  

在DbConn的构造函数中,你可能对$fromGetInstance的默认参数感到疑惑。在对象被直接实例化时,它能够提供保护:除非这个默认值变成e ,否则这段代码会报错。
  

表示成一个UML类图,解决办法如下:
  

如果你不选用这个“神秘参数”-类型保护,建立一个全局标记是另外一个选择,用它来验证你是通过getInstance方法来创建的对象。保护方式从“你知道它的名字”改变成“它存在于环境中”。
  

下面有个例子,它解释了为什么构造函数保护代码有一个全局的标识:
  class DbConn {
function DbConn {
$token = ‘__some_DbConn_instance_create_semaphore__’;
if ) {
trigger_error;
}
}
function &getInstance {
static $instance = array;
if {
$token = ‘__some_DbConn_instance_create_semaphore__’;
$GLOBALS = true;
$instance =& new DbConn;
unset;
}
  

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

这段代码中另外一个重点是引用操作&的用法。有两种地方需要使用&。第一种是在函数定义时,在函数名字前用来表示将返回一个引用。第二种是将新的DbConn对象赋值给$GLOBALS数组。
  

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

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

在getInstance方法内部使用静态变量来存储Singleton是一个显得干净的办法。第一个代码片断如下:
  class DbConn {
//
function &getInstance {
static $instance = false;
if $instance =& new DbConn;
return $instance;
}
}
  

Zend 1引擎在PHP4中不能存储静态变量的引用 。使用一个工作区存储静态数组,并且将这个单件实例的引用放置到一个已知的数组中。getInstance方法如下:
  class DbConn {
function DbConn {
if {
trigger_error;
}
}
function &getInstance {
static $instance = array;
if $instance0 =& new DbConn;
return $instance0;
}
}
  

这段代码很简单的选择了这个静态数组$instancede的第一个元素,用来保持单件DbConns实例的引用。
  

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

PHP5中的单件模式
  

PHP5中更容易实现单件模式,PHP5对于类内部变量和函数的访问控制被加强了。将DbConn::_construct构造方法设置为私有,这个类就不能被直接实例化。用UML图表示,PHP5的DbConn单件模式如下:
  

组合使用静态方法和静态变量保持这个实例,并且设置构造函数为私有,以防止直接实例化类而创建实例,代码如下:
  class DbConn {
/**
* static property to hold singleton instance
*/
static $instance = false;
/**
* constructor
* private so only getInstance method can instantiate
* @return void
*/
private function __construct {}
/**
* factory method to return the singleton instance
* @return DbConn
*/
public function getInstance {
if {
DbConn::$instance = new DbConn;
}
return DbConn::$instance;
}
}
  

下一节:《PHP设计模式介绍》第五章 注册模式
  请看下面的例子:,
‘The returned object is an instance of DbConn’);
$this->assertReference,

表示成一个UML类图,解决办法如下:,就像在DbConn类的前一个版本一样,在函数的定义和赋值部分需要引用操作符。

 Category: 用车知识

Leave a Reply