您的位置:首页 > 其它

Serialize/Unserialize破坏单例

2015-08-25 14:44 477 查看
·        作者: Laruence(   )
·        本文地址: http://www.laruence.com/2011/03/18/1909.html
·        转载请注明出处
我们经常采用如下方式定义单列:
1.       class Singleton {
2.           private
static$instance = NULL;
3.        
4.           /**
不容许直接调用构造函数 */
5.           private
function__construct() {
6.        
7.           }
8.        
9.           /**
不容许深度复制 */
10.        private
function__clone() {
11.        }
12.     
13.        public
staticfunctiongetInstance() {
14.            if (NULL === self::$instance)
{
15.                 self::$instance =
newself();
16.              }
17.     
18.            return self::$instance;
19.        }
20.    }
很多人都会记得对深度copy的保护,
但, 其实我们却疏忽了一点:
1.       <?php
2.       $a = Singleton::getInstance();
3.       $b =
unserialize(serialize($a));
4.        
5.       var_dump($a ===
$b);
6.       //bool(false)
呵呵,
可见还需要修补,
加上对序列化的保护:
1.       class Singleton {
2.           private
static$instance = NULL;
3.        
4.           /**
不容许直接调用构造函数 */
5.           private
function__construct() {
6.        
7.           }
8.        
9.           /**
不容许深度复制 */
10.        private
function__clone() {
11.        }
12.     
13.        /**
不容许serialize */
14.        private
function__sleep() {
15.        }
16.     
17.        /**
不容许unserialize */
18.        private 
function__wakeup() {
19.        }

20.     
21.        public
staticfunctiongetInstance() {
22.            if (NULL === self::$instance)
{
23.                 self::$instance =
newself();
24.              }
25.     
26.            return self::$instance;
27.        }
28.    }
然而,
有的时候我们是希望我们的单利类是能序列化的,
这个时候可以考虑如下的方式:
1.       class Singleton {
2.           private
static$instance = NULL;
3.        
4.           /**
不容许直接调用构造函数 */
5.           private
function__construct() {
6.        
7.           }
8.        
9.           /**
不容许深度复制 */
10.        private
function__clone() {
11.        }
12.     
13.        public 
function__wakeup() {
14.            self::$instance =
$this;
15.        }
16.     
17.        /**
需要在单利切换的时候做清理工作 */
18.        public
function__destruct() {
19.            self::$instance = NULL;
20.        }
21.     
22.        public
staticfunctiongetInstance() {
23.            if (NULL === self::$instance)
{
24.                self::$instance =
newself();
25.            }
26.     
27.            return self::$instance;
28.        }
29.    }
请注意上面,
我们在wakeup的时候,
切换了当前的单例实例,
来实现在序列化/反序列化的时刻保证单例.
另外,
对于一些包含全局资源的单例类,
我们需要定义析构函数,
来在切换的过程中做资源回收工作.
现在,
请大家仔细看看,
然后想想这段代码有没有什么问题?
接着往下看,
这段代码在有些条件下,
可能会达不到我们预期的目标,
比如:
1.       $a = Singleton::getInstance();
2.       $a =
unserialize(serialize($a));
3.        
4.       var_dump($a === Singleton::getInstance());
5.       //bool(false)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: