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)
· 本文地址: 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)
相关文章推荐
- Kafka 分布式消息系统详解
- 国外程序员常去的14个开发社区
- iOS第三方框架集合
- scrollview中嵌套viewpager出现的兼容问题
- Java字符串中判断是否有汉字
- 多线程下面日志输出-线程安全-消息队列循环输出
- ZT一篇从普华永道离开的人的文章:闲话我在普华永道的岁月
- PowerDesigner反向数据库时遇到[Microsoft][ODBC SQL Server Driver][SQL Server]无法预定义语句。SQLSTATE = 37错误解决方法
- 百度搜索URL参数含义
- BA-风阀水阀执行器接线图
- SQL RIGHT JOIN 关键字
- Ubuntu 14.04笔记本开机屏幕亮度调节
- 关于QSocket的释放的一个需要注意的情况
- 到底这些配置有哪些是可以自己后期加装的,而哪些又是无法自己后期加装的呢?可以后装加的配置是否比原装的要划算呢?
- 从今天开始,继续写一些技术类博客,分享给大家。
- HDU 1051 Wooden Sticks (贪心)
- OPENCV VS设置
- Robot Framework 教程 (5) - 连接Oracel数据库
- 小试Express
- Entity Framework 实体关系总结