设计模式学习之单件模式

如下内容是学习《Head First 设计模式》第五部分《单件模式》所得,主要就是一些原文摘抄和少量自己的总结。

单件模式定义

单件模式确保类只有一个实例,并提供一个全局访问点。

书中示例的 C++ 实现版源码

这个 Solution 的 SingletonPattern 工程里

书中示例的类图

Visio 原图见这里:

Singleton Pattern UML Class Diagram

关键代码片断

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&); // private and not implemented copy constructor
CSingleton& operator=(const CSingleton&); // private and not implemented = operator

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);
}
}

小结

  1. 单件模式的精华是通过设计来限制一个类产生多个实例的可能性,从而满足有且仅能有一个实例的类的设计需求。
  2. 为了实现上述目标,采用了私有化构造函数和提供一个公开的获取唯一实例的接口。
  3. 要记得将复制构造函数和重载赋值运算符也声明为私有,不然类的用户仍然可以使用CSingleton ObjA(*CSingleton::GetInstance())CSingleton ObjB = *CSingleton::GetInstance())的写法来得到第二、第三甚至更多的实例对象。
  4. 为了实现多线程安全,在创建唯一实例的时候会采用多线程同步设施如临界区、事件等来保证,声明实例指针使用 volatile 关键字。
  5. 在 Java 等语言中有「同步方法」和「急切」创建实例等方式来解决多线程的问题,C++ 中貌似都不太适用,使用 volatile 加双重检查加锁相对靠谱。
  6. 记得在合适的地方释放单例以及时和正确地回收资源。