如下内容是学习《Head First 设计模式》第五部分《单件模式》所得,主要就是一些原文摘抄和少量自己的总结。
单件模式定义
单件模式确保类只有一个实例,并提供一个全局访问点。
书中示例的 C++ 实现版源码
这个 Solution 的 SingletonPattern 工程里。
书中示例的类图
Visio 原图见这里:
关键代码片断
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class CSingleton { public: static CSingleton* GetInstance();
static void ReleaseInstance();
void DoSomething();
private: CSingleton(); CSingleton(const CSingleton&); CSingleton& operator=(const CSingleton&);
volatile static CSingleton* m_sUniqueInstance; static HANDLE m_hSync; };
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| volatile CSingleton* CSingleton::m_sUniqueInstance = NULL; HANDLE CSingleton::m_hSync = ::CreateEvent(NULL, FALSE, TRUE, NULL);
CSingleton* CSingleton::GetInstance() { if (NULL == m_sUniqueInstance) { WaitForSingleObject(m_hSync, INFINITE); if (NULL == m_sUniqueInstance) { m_sUniqueInstance = new CSingleton(); } SetEvent(m_hSync); }
return (CSingleton*)m_sUniqueInstance; }
void CSingleton::ReleaseInstance() { if (0 != m_sUniqueInstance) { delete m_sUniqueInstance; m_sUniqueInstance = NULL; }
if (NULL != m_hSync) { CloseHandle(m_hSync); } }
|
小结
- 单件模式的精华是通过设计来限制一个类产生多个实例的可能性,从而满足有且仅能有一个实例的类的设计需求。
- 为了实现上述目标,采用了私有化构造函数和提供一个公开的获取唯一实例的接口。
- 要记得将复制构造函数和重载赋值运算符也声明为私有,不然类的用户仍然可以使用
CSingleton ObjA(*CSingleton::GetInstance())
和CSingleton ObjB = *CSingleton::GetInstance())
的写法来得到第二、第三甚至更多的实例对象。 - 为了实现多线程安全,在创建唯一实例的时候会采用多线程同步设施如临界区、事件等来保证,声明实例指针使用 volatile 关键字。
- 在 Java 等语言中有「同步方法」和「急切」创建实例等方式来解决多线程的问题,C++ 中貌似都不太适用,使用 volatile 加双重检查加锁相对靠谱。
- 记得在合适的地方释放单例以及时和正确地回收资源。