单例模式也称为单件模式,单子模式,可能是使用最广泛的设计模式。其意图是保证一个类只有一个实例,且对外只提供一个接口,该实例可以被所以程序模块共享。
“设计模式”一书给出了不错的实现,定义一个单例类,使用类的私有静态指针变量指向类的唯一实例,并用一个公用的静态方法获取该实例。
单例模式通过类本身来管理唯一单例,唯一的实例是类的一个普通对象,但设计这个类的时候,让他只能创建一个实例并提供对次实例的全局访问。唯一实例类Singleton在静态成员中隐藏创建实例的操作。习惯上把这个成员函数叫做instance(),它的返回值是唯一实例的指针。
class CSingleton
{
privace:
CSingleton()
{
}
stitac CSingleton *m_pInstance;
public:
static CSingleton *GetInstance()
{
if(m_pInstance == NULL)
{
m_pInstance = new CSingleton();
return m_pInstance
}
}
};
用户唯一访问实例的方法只是GetInstance()成员函数。如果不调用这个函数,是不可能成功的。因为类的构造函数是私有的。
单例类CSingleton有以下特征:
- 它有一个指向唯一实例的静态指针m_pInstance,并且是私有;
- 它有一个共有函数,可以获取这个实例,并且在需要的时候创建该实例;
- 它的构造函数是私有的,这样就不能从别处创建该类的实例;
但是读者也发现了这个问题:m_pInstance指向的空间什么时候释放呢?还有就是,该实例的析构函数什么时候执行?
如果在类的析构行为中有其他的操作,比如关闭文件,释放外部资源,那么上面的代码就会出错。
一个妥善的办法就是让这个类自己知道什么时候把自己析构,或者说把删除自己的操作挂在操作系统的某个合适位置,使其在合适的时候自动执行。
我们知道,在程序结束的时候,系统会自动析构所以的全局变量。事实上,系统也会析构所有的类的静态成员变量,就像这些静态成员也是全局变量一样。利用这个特征,我们可以在单例类中定义一个这个的静态成员变量,而它的唯一工作就是把在析构函数中删除单例类的实例。
class CSingleton
{
privace:
CSingleton()
{
}
stitac CSingleton *m_pInstance;
class CGarbo
{
pubulic:
~CGarbo()
{
if(CSingleton::m_pinstance)
delete CSingleton::m_instance;
}
}
public:
static CSingleton *GetInstance()
{
if(m_pInstance == NULL)
{
m_pInstance = new CSingleton();
return m_pInstance
}
}
};
类CGarbo被定义为CSingleton的私有内嵌类,防止此类在其他地方调用。
程序运行结束时,系统会调用CSingleton的静态成员Garbo的析构函数,该析构函数会删除单例的唯一实例。
考虑到线程安全,异常安全,可以做一下拓展
class CSingleton
{
privace:
CSingleton()
{
}
stitac CSingleton *m_pInstance;
class CGarbo
{
pubulic:
~CGarbo()
{
if(CSingleton::m_pinstance)
delete CSingleton::m_instance;
}
}
public:
static CSingleton *GetInstance()
{
if(m_pInstance == NULL)
{
lock();
if(m_pInstance == NULL)
m_pInstance = new CSingleton();
unlock();
return m_pInstance
}
}
};
之所以在GetInstance函数里面对p_mInstance做两次判断,因为该方法调用一次就会产生对象,m_pInstance == NULL在大部分时间都是false,这样会大大提高效率。