[置顶] head first设计模式之单例模式 c++解读

最近学习了下《head first设计模式》,先对单例模式做个简单的总结。


为什么不用全局变量?

单例模式用一句话概括就是只产生一个对象,那为啥不用全局变量来代替单例模式呢?

全局变量是程序在一开始就创建好对象,如果这个对象非常耗费资源,程序的执行又用不到它,那就太浪费了。而单例可以在需要它的时候再创建它。

使用场景

线程池,缓存,处理偏好设置,注册表的对象,日志对象,充当打印机、显卡等设备的驱动程序的对象。

实现

一句话,构造函数为私有就可以实现了。
看下c++中的一个简单实现:
singleton.h
//2013-4-10 10:07
//单例设计模式

class MySingleton
{
public:
	~MySingleton();

	static MySingleton* GetInstance();
private:
	MySingleton();

};

singleton.cpp

#include "singleton.h"

MySingleton::~MySingleton()
{

}

MySingleton::MySingleton()
{

}

MySingleton* MySingleton::GetInstance()
{
	static MySingleton* pInstance = new MySingleton();

	return pInstance;
}

问题1

实现很简单,这样就保证只会产生一个实例了。但是这样会产生一个问题。什么问题呢???
可以写个客户端的代码验证:
int main(int argc,char* argv[])
{
	MySingleton* pMySingleton = MySingleton::GetInstance();

	MySingleton* pMySingleton1 = MySingleton::GetInstance();

	delete pMySingleton;

	delete pMySingleton1;
	return 0;
}

是的,释放内存就会出问题了。
这样不得不考虑重新实现了,怎么才能保证释放一次并且自动释放?

有一个技巧:
参考了http://www.cnblogs.com/binxindoudou/p/3261082.html

我的实现如下:

//singleton.h
#pragma once

#include <iostream>
using namespace std;

class MySingleton
{

private:
	static MySingleton* pInstance;

public:

	static MySingleton* GetInstance();

	class SingletonGarbo // 它的唯一工作就是在析构函数中删除CSingleton的实例  
	{
	public:
		~SingletonGarbo()
		{  
			//测试用
			cout<<"SingletonGarbo::~SingletonGarbo()"<<endl;
			if (0 != MySingleton::pInstance)
			{
				delete MySingleton::pInstance;
				MySingleton::pInstance = 0;
			}
		}
	};
private:
	MySingleton();

	~MySingleton();//防止在不合适的地方释放了

};

//singleton.cpp
#include "singleton.h"

MySingleton* MySingleton::pInstance = 0;
MySingleton::SingletonGarbo garbo;

MySingleton::~MySingleton()
{
	
}

MySingleton::MySingleton()
{

}

MySingleton* MySingleton::GetInstance()
{
	if ( pInstance == 0)
	{
		pInstance = new MySingleton();
	}

	return pInstance;
}

这样就保证在程序结束的时候释放单例对象了。应该还有别的比较好的实现,类中类总感觉不好,还没想到。如果有了补充。

问题2

还会不会有问题呢?
多线程。是的,GetInstance()方法中多线程可能会出问题。
if ( pInstance == 0)
//线程1访问,刚好到此时间片轮换
{
	pInstance = new MySingleton();
}

return pInstance;



//线程2开始执行
if ( pInstance == 0)
{
	pInstance = new MySingleton();
}

return pInstance;


这样就产生两个对象了。

解决办法是同步即可,伪代码:

MySingleton* MySingleton::GetInstance()
{
	lock();
	if ( pInstance == 0)
	{
		pInstance = new MySingleton();
	}
	unlock();

	return pInstance;
}


但是这样效率太低了,每次获取对象的时候都要同步,一个同步会使效率低100倍。

可以第一次进行同步,下次就不用了。伪代码:

MySingleton* MySingleton::GetInstance()
{
	if ( pInstance == 0)
	{
		lock();
		if ( pInstance == 0)
		{
			pInstance = new MySingleton();
		}
		unlock();}
	return pInstance;
}

2014-4-24更新
可以继承吗?

参考两篇文章:

1

[C++]通过模板类巧妙实现单件模式的继承

http://hi.baidu.com/gookings/item/68f471ca0da60a17b67a24a2

2,

可以继承的C++ Singleton基类

http://www.gocalf.com/blog/cpp-singleton.html

3

Singleton模式是常用的设计模式之一,但是要实现一个真正实用的设计模式却也不是件容易的事情。

http://www.cppblog.com/dyj057/archive/2005/09/20/346.html







你可能感兴趣的:([置顶] head first设计模式之单例模式 c++解读)