单例
单例模式,希望在程序上下文中,仅对对象做一次实例化。
问题
避免方式
- clone 由于clone时,会调用对象的
__clone
magic method. 因此,可以将__clone
设置为私有,使clone失效。
单例模式
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class Singleton { private static $instance = NULL;
private function __construct() { }
private function __clone() { }
public static function getInstance() { if (NULL === self::$instance) { self::$instance = new self(); } return self::$instance; } }
|
unserialize
将Singleton 将对象序列化,再进行反序列化。可以构造新的单例对象。这种情况下,鸟哥给出的解决方案是:(使用__wakeup()
方法)[http://www.laruence.com/2011/03/18/1909.html]。
但是,通过对比发现,这个代码其实会有问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| <?php class Singleton { private static $instance = NULL; private $data = '';
private function __construct() { }
private function __clone() { }
public function __wakeup() { self::$instance = $this; }
public static function getInstance() { if (NULL === self::$instance) { self::$instance = new self(); } return self::$instance; }
}
$a = Singleton::getInstance(); $b = unserialize(serialize($a));
var_dump($b === $a);
|
因为unserialize 其实会实例化一个单例对象,和原来实例化的单例对象不是一个对象。因此,会引起dump 不一致的情况。这个暂时无法避免。