意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
单件模式交互中只有一个类,他使自身的对象永远为一。常使用于数据库类、注册表类、日志类等。下面来看下该模式的PHP实现:
<?php
class Singleton {
private static $_instance;
private function __construct(){}
private function __clone(){}
public static function getInstance() {
if(!self::$_instance) {
self::$_instance = new self();
}
return self::$_instance;
}
}
?>
第一:我们把构造函数定为私有的,所以外部不能实例化本类;
第二:定义一个公有的静态方法,于是我们可以不用实例化对象也能调用该方法:Singleton::getInstance;
第三:定义一个私有的静态变量用于持有自身实例;
第四:覆盖__clone方法为私有,以防通过拷贝出现多于一个对象。
上面的例子有可能在继承中有一些问题,我们改写如下:
<?php
abstract class Singleton {
private static $_instance = array();
private function __construct(){}
final private function __clone(){}
final public static function getInstance() {
$class_name = get_called_class(); //php>=5.3
if(!isset(self::$_instance[$class_name])) {
self::$_instance[$class_name] = new $class_name();
}
return self::$_instance[$class_name];
}
}
?>
或者
<?php
abstract class Singleton {
private static $_instance = array();
protected static $class= __CLASS__; //在子类中必需覆写
private function __construct(){}
final private function __clone(){}
final public static function getInstance() {
if(!isset(self::$_instance[static::$class])) {
self::$_instance[static::$class] = new static::$class();
}
return self::$_instance[static::$class];
}
}
?>
这里一个例子使用get_called_class()方法,一个使用static关键字。这都是利用php5.3以后的延迟静态绑定这一特性完成的。