IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

Serialize/Unserialize破坏单例

风雪之隅 2011-03-21 00:10:23 累计浏览 2,571 次
本机暂存

我们经常采用如下方式定义单列:

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, :)

同分类推荐文章

  1. 如何写好设计文档? (2026-06-23 08:00:00)
  2. Designing With Uncertainty: How AI Supercharges Probabilistic Thinking (2026-06-16 23:00:00)
  3. The Benefits Of Cognitive Inclusion In UX Research (2026-06-10 18:00:00)

查看更多 设计 文章 →

建议继续学习

  1. 使用gettext来支持PHP的多语言 (累计阅读 39,270)
  2. WordPress插件开发 -- 在插件使用数据库存储数据 (累计阅读 29,164)
  3. Paypal接口详细代码(PHP版,非API接口) (累计阅读 19,408)
  4. 我的PHP,Python和Ruby之路 (累计阅读 13,147)
  5. include(“./file.php”)和include(“file.php”)区别 (累计阅读 12,789)
  6. 15个最好的免费开源电子商务平台 (累计阅读 12,541)
  7. Redis消息队列的若干实现方式 (累计阅读 12,088)
  8. 到底什么是MVC? (累计阅读 11,867)
  9. 整理了一份招PHP高级工程师的面试题 (累计阅读 11,708)
  10. Rolling cURL: PHP并发最佳实践 (累计阅读 11,488)