单例模式通过类本身来管理其唯一实例,这种特性提供了解决问题的方法。唯一的实例是类的一个普通对象,但设计这个类时,让它只能创建一个实例并提供对此实例的全局访问。唯一实例类Singleton在静态成员函数中隐藏创建实例的操作。
01.class CSingleton 02.{ 03. private: 04. CSingleton() //构造函数是私有的 05. { 06. } 07. CSingleton(const CSingleton &); 08. CSingleton & operator = (const CSingleton &); 09. public: 10. static CSingleton & GetInstance() 11. { 12. static CSingleton instance; //局部静态变量 13. return instance; 14. } 15.};
关于Singleton(const Singleton);和 Singleton & operate = (const Singleton&);函数,需要声明成私有的,并且只声明不实现。
考虑到线程安全、异常安全,可以做以下扩展:
01.class Lock 02.{ 03.private: 04. CCriticalSection m_cs; 05.public: 06. Lock(CCriticalSection cs) : m_cs(cs) 07. { 08. m_cs.Lock(); 09. } 10. ~Lock() 11. { 12. m_cs.Unlock(); 13. } 14.}; 15. 16.class Singleton 17.{ 18.private: 19. Singleton(); 20. Singleton(const Singleton &); 21. Singleton& operator = (const Singleton &); 22. 23.public: 24. static Singleton *Instantialize(); 25. static Singleton *pInstance; 26. static CCriticalSection cs; 27.}; 28. 29.Singleton* Singleton::pInstance = 0; 30. 31.Singleton* Singleton::Instantialize() 32.{ 33. if(pInstance == NULL) 34. { //double check 35. Lock lock(cs); //用lock实现线程安全,用资源管理类,实现异常安全 36. //使用资源管理类,在抛出异常的时候,资源管理类对象会被析构,析构总是发生的无论是因为异常抛出还是语句块结束。 37. if(pInstance == NULL) 38. { 39. pInstance = new Singleton(); 40. } 41. } 42. return pInstance; 43.}
之所以在Instantialize函数里面对pInstance 是否为空做了两次判断,因为该方法调用一次就产生了对象,pInstance == NULL 大部分情况下都为false,如果按照原来的方法,每次获取实例都需要加锁,效率太低。而改进的方法只需要在第一次 调用的时候加锁,可大大提高效率。