基于PHP语言自身的一些特性,在实现设计模式时,有着不同于JAVA等语言的特点,这里说一说实现单例模式时需要注意的问题。
先看看《PHP高级程序设计——模式、框架与测试》(Pro PHP——Patters, Frameworks, Testing and More)中的例子(书中每18页):
-
class Database {
-
private $_db;
-
static $_instance;
-
-
private function __construct() {
-
$this->_db = pg_connect('dbname=example_db');
-
}
-
-
private function __clone() {}; //此处中译本漏掉了function关键字
-
-
public static function getInstance() {
-
if ( ! (self::$_instance instanceof self) ) {
-
self::$_instance = new self();
-
}
-
return self::$_instance;
-
}
-
-
public function query($sql) {
-
return pg_query($this->_db, $sql);
-
}
-
}
这里面有个问题,就是用继承的方式可以使用构造函数生成子类的对象,可能在不小心的情况下破坏了单件机制。代码如下:
-
class subDatabase
-
{
-
public function __construct()
-
{
-
$this->_db = pg_connect('dbname=example_db');
-
}
-
}
在JAVA中,这种情况是不会出现的,这是因为JAVA的构造函数无论显式或隐式,都必须调用父类的构造函数,而父类的构造函数一旦被设置为private,就不能为子类访问。因此,拥有私有构造函数的类将不能被子类化(继承)。
而在PHP中,构造函数无须显式或隐式地调用父类的构造函数,就造成了上面的情况。
堵住这个漏洞的办法也很简单,只要将Database的构造函数设置为final,子类将无法对其进行重写,虽然仍然能够子类化该类,但却无法实例化。
代码如下:
-
class Database {
-
private $_db;
-
static $_instance;
-
final private function __construct() {
-
$this->_db = pg_connect('dbname=example_db');
-
}
-
private function __clone() {}; //此处中译本漏掉了function关键字
-
public static function getInstance() {
-
if ( ! (self::$_instance instanceof self) ) {
-
self::$_instance = new self();
-
}
-
return self::$_instance;
-
}
-
public function query($sql) {
-
return pg_query($this->_db, $sql);
-
}
-
}
至于类中私有化__clone函数的作用,请见《PHP高级程序设计——模式、框架与测试》第18页的讲解。
更简单的方式,给类添加final,使其无法被继承:
-
final class Database {
-
private $_db;
-
static $_instance;
-
private function __construct() {
-
$this->_db = pg_connect('dbname=example_db');
-
}
-
private function __clone() {}; //此处中译本漏掉了function关键字
-
public static function getInstance() {
-
if ( ! (self::$_instance instanceof self) ) {
-
self::$_instance = new self();
-
}
-
return self::$_instance;
-
}
-
public function query($sql) {
-
return pg_query($this->_db, $sql);
-
}
-
}
再来说说JAVA中实现单例的“懒汉模式”和“饿汉模式”。其中饿汉模式是指在类创建时就创建了实例,具体代码类似于:
-
public class Singleton{
-
private static Singleton singleton = new Singleton ();
-
private Singleton (){}
-
public Singleton getInstance(){
-
return singletion;
-
}
-
}
此种方式,在PHP中无法实现,因为PHP中的类静态变量只能用常量赋值,不能用变量、表达式赋值。因此PHP中仅能实现“懒汉模式”。
阅读(2092) | 评论(0) | 转发(0) |