C++ 单例模式

原创 2016年01月22日 17:12:52

单例模式Singleton(),应该是设计模式中最简单的一种模式,表明在整个程序执行周期内,类的实例对象只能存在一个。虽然很简单,但是应用场景却是很多,比如windows的任务管理器;windows的回收站,在整个系统运行中,回收站一直维护着一个实例;应用程序的日志应用,一般都何用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。

UML_Singleton

class CSingleton
{
public:
    static CSingleton* getInstance()
    {
        if (m_pInstance == NULL)
        {
            m_pInstance = new CSingleton;
        }

        return m_pInstance;
    }

protected:
    CSingleton() {}
    virtual ~CSingleton() {}

private:
    static CSingleton* m_pInstance;
};

CSingleton* CSingleton::m_pInstance = NULL;

上面的代码是最简单的一种单例模式实现,主要有几个地方需要注意。首先是单例模式只能通过getIntance() 实现,而不能通过构造函数的方式实现,所以必须设置构造函数是私有的或者保护的。其次,既然只能在整个程序运行周期存在一个对象,那么私有的成员变量应该设置为静态变量,同理,那么函数的修改也应该是静态。静态成员变量只能在类外显示声明,因为它不属于某一个对象,而属于这个类共享。


程序代码最终是希望有良好的扩展性和稳定性,如果上面的代码在多线程环境中,肯定不能保证实例对象只存在一个,所以需要修改在多线程中是满足单例模式的定义。其次,单例模式希望实例的是某种类型或者性质的对象,那么需要修改为模板类的定义,这样在以后的需求改动中,就避免了不避免的麻烦。

template <typename T>
class CSingleton
{
public:
    static T* getInstance()
    {
        if (NULL == m_pInstance)
        {
            boost::unique_lock<boost::mutex> Lock(m_Mutex);
            if (NULL == m_pInstance)
            {
                //std::cout << "Thread id" << boost::this_thread::get_id() << std::endl;
                m_pInstance = new T;
            }
        }

        return m_pInstance;
    }

protected:
    CSingleton(void) {}
    virtual ~CSingleton(void) {}

private:
    static T* m_pInstance;
    static boost::mutex m_Mutex;
};

template<typename T>
T* CSingleton<T>::m_pInstance = NULL;

template<typename T>
boost::mutex CSingleton<T>::m_Mutex;

首先是模板形式,这个比较简单,读者能一眼看出其修改方式。其他改动的地方首先是if (NULL == m_pInstance) 判断为空条件写了两个,第一个是为了避免加锁解锁的耗时操作,多线程中互斥量的加锁解锁比较耗时的,所以在以后不为空的情况,都没必要进行加锁解锁,只有在第一次为空的情况,才到内部就行加锁操作。


程序代码健壮了,但是类的析构函数也是私有的,那说明如果有程序员想显示delete是不可能,那么只能增加相应的函数去删除对象。

template <typename T>
class CSingleton
{
public:
    static T* getInstance()
    {
        if (NULL == m_pInstance)
        {
            boost::unique_lock<boost::mutex> Lock(m_Mutex);
            if (NULL == m_pInstance)
            {
                //std::cout << "Thread id" << boost::this_thread::get_id() << std::endl;
                m_pInstance = new T;
                atexit(destroy);
            }
        }

        return m_pInstance;
    }

    static void destroy()
    {
        if (m_pInstance)
        {
            delete m_pInstance;
            m_pInstance = NULL;
        }
    }

protected:
    CSingleton(void) {}
    virtual ~CSingleton(void) {}

private:
    static T* volatile m_pInstance;
    static boost::mutex m_Mutex;
};

template<typename T>
T* volatile CSingleton<T>::m_pInstance = NULL;

template<typename T>
boost::mutex CSingleton<T>::m_Mutex;

上面的代码多了destroy函数来delete对象,和int atexit (void (*function) (void)); 来调用它,atexit()用来设置一个程序正常结束前调用的函数. 当程序通过调用exit()或从main 中返回时, 参数function 所指定的函数会先被调用, 然后才真正由exit()结束程序。
而C++关键volatile关键字,多线程的volatile,当两个线程都要用到某一个变量且该变量的值会被改变时,应该用 volatile 声明,该关键字的作用是防止优化编译器把变量从内存装入 CPU 寄存器中。如果变量被装入寄存器,那么两个线程有可能一个使用内存中的变量,一个使用寄存器中的变量,这会造成程序的错误执行。volatile 的意思是让编译器每次操作该变量时一定要从内存中真正取出,而不是使用已经存在寄存器中的值。详细参考C/C++ volatile让你看的更明白

参考资料:
【1】http://blog.csdn.net/likika2012/article/details/11483167
【2】http://www.jellythink.com/archives/82
【3】https://gist.github.com/daniebker/2299755
【4】http://blog.csdn.net/wwang196988/article/details/6623387

文章标题

网络传输协议KCPKCP简介KCP是一种快速的可靠的ARQ协议(A Fast and Reliable ARQ Protocol),但严格意义上讲KCP并不是一种网络传输协议,因为KCP并不负责网络底...

KCP网络传输协议

# 网络传输协议KCP ## KCP简介 KCP是一种快速的可靠的ARQ协议(A Fast and Reliable ARQ Protocol),但严格意义上讲KCP并不是一种网络传输协议...

Headfirst(五)单例模式C++实现

  • 2015年10月21日 15:24
  • 495KB
  • 下载

C++单例模式示例代码

  • 2015年09月29日 18:21
  • 2KB
  • 下载

C和C++的面向对象专题(7)——单例模式解决静态成员对象和全局对象的构造顺序难题

本专栏文章列表一、何为面向对象二、C语言也能实现面向对象三、C++中的不优雅特性四、解决封装,避免接口五、合理使用模板,避免代码冗余六、C++也能反射七、单例模式解决静态成员对象和全局对象的构造顺序难...

C++ 单例模式

  • 2016年09月28日 20:04
  • 2KB
  • 下载

C++单例模式的模板基类

单例模式是很常用的设计模式,如果希望系统中某个类的对象只能有一个或者有一个就够了,那么便可以采用单例模式来解决。 下面用C++实现一个单例模板类,那么其他的类只需继承它,便可以成为单例类。 本例中...

c++ 单例模式源码

  • 2011年08月17日 09:20
  • 571B
  • 下载

c++线程安全单例模式

  • 2010年04月01日 16:08
  • 2KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++ 单例模式
举报原因:
原因补充:

(最多只允许输入30个字)