music unfamous original game design efficient software wtf
life ui algorithm fix programming

设计模式 Singleton -- C++描述

作者:trinity  C/C++    2014-10-11   

应用背景   

    Singleton 是一个经常会用到的模式,因为现实世界很多对象是唯一的,对于代码,单例是很方便管理的。比如IO操作,配置文件读取。

    这也是一个很简单的模式,和其他模式交织使用也应该是最多的。核心就是:对象实例只有一个。

代码示例(C++)

    一段简单的,经典的 Singleton 代码:

class CSingleton{
     private:
	static CSingleton* m_inst;
     private:
	CSingleton(){
		m_inst = 0;
	}
     public:
	static CSingleton* GetInstance(){
		if (!m_inst){
			m_inst = new CSingleton();
		}
		return m_inst;
	}
};

这样 GetInstance() 时候,还有最终释放返回的指针的问题,网上有朋友给出了自动释放的方案,代码如下:

#ifndef CSingleton_H_
#define CSingleton_H_

class CSingleton{
     private:
	class CAutoDelete{
	public:
		~CAutoDelete(){
			if (CSingleton::m_inst){
				delete CSingleton::m_inst;
				CSingleton::m_inst = 0;
			}
		}
	};
     private:
	static CAutoDelete m_gc_;
	static CSingleton* m_inst;
     private:
	CSingleton(){
		m_inst = 0;
	}
     public:
	static CSingleton* GetInstance(){
		if (!m_inst){
			m_inst = new CSingleton();
		}
		return m_inst;
	}
};

CSingleton* CSingleton::m_inst = 0;
CSingleton::CAutoDelete CSingleton::m_gc_;

//// class CSingleton declaration end////

//wrap funtion
template<typename T>
T* GetInstance(){
	return (T*)CSingleton::GetInstance();
}

#endif


使用示例:


class CDerive :public CSingleton{
     public:
	void DoSmthing(){
		printf("Hello world");
	}
};

int main()
{
	CDerive * d = GetInstance<CDerive>();
	d->DoSmthing();

	return 0;
}

    在上面的例子中,CAutoDelete 内嵌类能够自动释放 GetInstance()函数申请的内存,但这不是必要的,因为毕竟整个进程生命周期内只会有一个对象存在,其实,即使不释放,也不是什么大问题。所以更多的做法是提供一个 Release 函数来在进程结束时释放内存。

    同时,上面的 Singleton 实现采用了继承的方式,还有采用宏的方式,暂不举例(不喜欢MFC式的宏)。

    下面用模版方式结合 Release 释放的方式实现一个:

另一个实现


template <typename T>
class singleton{
     private:
	static T* m_inst;
	singleton(){}
	~singleton(){}
     public:
	static T* GetInstance();
	static void Release();
};

template <typename T>
T* singleton<T>::m_inst = new T();

template <typename T>
T* singleton<T>::GetInstance()
{
	return m_inst;
}

template <typename T>
void singleton<T>::Release()
{
	delete m_inst;
	m_inst = 0;
}
调用方式



class student{
	int number;
     public:
	student(){
		number = 5;
	}

	int GetNumber(){
		return number;
	}
};

int main()
{
	int * a = singleton<int>::GetInstance();

	student* stu = singleton<student>::GetInstance();
	if (stu){
		printf("%d\n",stu->GetNumber());
	}
	
	return 0;
}
     上面的实现仍然有一个弊端--并不是线程安全的。