Serialize/Unserialize破坏单例


·        作者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)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值