Serialize/Unserialize破坏单例
浏览:1862次 出处信息
我们经常采用如下方式定义单列:
- 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的保护, 但, 其实我们却疏忽了一点:
- $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,
建议继续学习:
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
扫一扫订阅我的微信号:IT技术博客大学习
<< 前一篇:防止伪造跨站请求的小招式
后一篇:可序列化单例模式的遗留问题答案 >>
文章信息
- 作者:雪候鸟 来源: 风雪之隅
- 标签: Serialize Unserialize 单例
- 发布时间:2011-03-21 00:10:23
近3天十大热文
- [72] Twitter/微博客的学习摘要
- [64] find命令的一点注意事项
- [64] IOS安全–浅谈关于IOS加固的几种方法
- [62] 如何拿下简短的域名
- [62] Oracle MTS模式下 进程地址与会话信
- [61] Go Reflect 性能
- [61] android 开发入门
- [61] 流程管理与用户研究
- [57] 图书馆的世界纪录
- [56] 【社会化设计】自我(self)部分――欢迎区