C++设计模式之单例模式

来源:互联网 发布:淘宝 笑涵阁 猫腻 编辑:程序博客网 时间:2024/05/24 06:09

单例模式也称为单件模式,单子模式,可能是使用最广泛的设计模式。其意图是保证一个类只有一个实例,且对外只提供一个接口,该实例可以被所以程序模块共享。
“设计模式”一书给出了不错的实现,定义一个单例类,使用类的私有静态指针变量指向类的唯一实例,并用一个公用的静态方法获取该实例。
单例模式通过类本身来管理唯一单例,唯一的实例是类的一个普通对象,但设计这个类的时候,让他只能创建一个实例并提供对次实例的全局访问。唯一实例类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,这样会大大提高效率。