- 本文地址: https://www.laruence.com/2011/03/18/1909.html
- 转载请注明出处
我们经常采用如下方式定义单列:
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; } }
很多人都会记得对深度copy的保护, 但, 其实我们却疏忽了一点:
<?php $a = Singleton::getInstance(); $b = unserialize(serialize($a)); var_dump($a === $b); //bool(false)
呵呵, 可见还需要修补, 加上对序列化的保护:
class Singleton { private static $instance = NULL; /** 不容许直接调用构造函数 */ private function __construct() { } /** 不容许深度复制 */ private function __clone() { } /** 不容许serialize */ private function __sleep() { } /** 不容许unserialize */ private function __wakeup() { } public static function getInstance() { if (NULL === self::$instance) { self::$instance = new self(); } return self::$instance; } }
然而, 有的时候我们是希望我们的单利类是能序列化的, 这个时候可以考虑如下的方式:
class Singleton { private static $instance = NULL; /** 不容许直接调用构造函数 */ private function __construct() { } /** 不容许深度复制 */ private function __clone() { } public function __wakeup() { self::$instance = $this; } /** 需要在单利切换的时候做清理工作 */ public function __destruct() { self::$instance = NULL; } public static function getInstance() { if (NULL === self::$instance) { self::$instance = new self(); } return self::$instance; } }
请注意上面, 我们在wakeup的时候, 切换了当前的单例实例, 来实现在序列化/反序列化的时刻保证单例.
另外, 对于一些包含全局资源的单例类, 我们需要定义析构函数, 来在切换的过程中做资源回收工作.
现在, 请大家仔细看看, 然后想想这段代码有没有什么问题?
接着往下看, 这段代码在有些条件下, 可能会达不到我们预期的目标, 比如:
$a = Singleton::getInstance(); $a = unserialize(serialize($a)); var_dump($a === Singleton::getInstance()); //bool(false)
大家可以想想为什么这样,, 如果不想想的, 就看我的下一篇文章吧.
最后, 做个广告,,,, 在新浪微博关注我吧: http://t.sina.com.cn/laruence, 🙂
betworld easy to play, get real money
truthbet
The best sites in Thailand and make good money
ltobet
Good I appreciated your work very thanks
[…] 本文地址: http://www.laruence.com/2011/03/18/1909.html […]
[…] 本文地址: http://www.laruence.com/2011/03/18/1909.html […]
[…] 18 Mar 11 Serialize/Unserialize破坏单例 […]
鸟哥,最近经常 502 啊。
把实现的资源给重清了,看了以后还是受益匪浅~
LZ,请问对单例类进行serialize有什么实际应用吗?好像没怎么用过,也想不出来哪里可以用,求教。
恩,看懂了一半,谢谢分享!
[…] http://www.laruence.com/2011/03/18/1909.html Serialize/Unserialize破坏单例 […]
[…] 本文地址: http://www.laruence.com/2011/03/18/1909.html […]
[…] ="http://www.laruence.com/feed"; 在上一篇文章Serialize/Unserialize破坏单例的最后, 我留下了一个问题, 为了让大家能思考, 我就单独再写一篇, […]
@devil_si 学习PHP的话, 最重要的就是PHP手册了, 入门的话,推荐<PHP程序设计第二版>, http://product.china-pub.com/46509. 🙂
博主您好,能推荐几本学习php的书籍吗 谢谢。