0%

单例设计模式

单例模式(singleton):保证一个类仅有一个实例,并提供一个访问它的全局访问点。

如何保证一个类只有一个实例并且这个实例易于被访问呢?一个全局变量使得一个对象可以被访问,但它不能防止你实例化多个对象。一个更好的办法是,让类自身负责保存它的唯一实例,这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法,这就是 Singleton 模式。

Singleton 类UML图

img

Singleton 类,定义一个 GetInstance 操作,允许客户访问它的唯一实例。GetInstance 是一个静态方法,主要负责创建自己的唯一实例。

Singleton 模式使得这个唯一实例是类的一般实例,但该类被写成只有一个实例能被创建。做到这一点的一个常用方法是将创建这个实例的操作隐藏在一个类操作(即一个静态成员函数或者一个类方法)后面,由它保证只有一个实例被创建。这个操作可以访问保存唯一实例的变量,而且它可以保证这个变量在返回值之前用这个唯一实例初始化。

懒汉模式:单例模式处理方式要在第一次被引用时,才会将自己实例化,其返回值直到被第一次访问时才创建和保存。

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
class Singleton
{
private:
static Singleton *instance;
Singleton()//让其private,这样外部程序不能通过其实例化。Singleton obj;错误
{
}
public:
static Singleton* GetInstance()//类操作,即一个静态成员函数
{
if (instance == NULL)//没有实例化的情况下在去实例
{
instance = new Singleton;
}
return instance;
}
static void DestroyInstance()
{
if (instance != NULL)
{
delete instance;
instance = NULL;
}
}
};
Singleton* Singleton::instance = NULL;//静态成员变量类外初始化

客户端代码:

客户端不再考虑是否需要去实例化的问题了,而把责任给了应该负责的类去处理。

1
2
3
4
5
6
7
8
9
10
11
int main()
{
Singleton *s1 = Singleton::GetInstance();
Singleton *s2 = Singleton::GetInstance();
//Singleton *s2 = s1->GetInstance();
if (s1 == s2)
{
cout << "两个对象是相同的实例" << endl;
}
return 0;
}

考虑到多线程安全。在多线程的程序中,多个线程同时访问 Singleton 类,调用 GetInstance() 方法,会有可能造成创建多个实例的情况。

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
33
class Singleton
{
private:
static Singleton *instance;
Singleton()
{
}
public:
static Singleton* GetInstance()//类操作,即一个静态成员函数
{
//双重锁定
if (NULL == instance)
{
lock();//实例未创建的情况下加锁,借用其他类实现
if (NULL == instance)
{
instance = new Singleton;
}
unlock();
}
return instance;
}
static void DestroyInstance()
{
if (instance != NULL)
{
delete instance;
instance = NULL;
}
}
};

Singleton* Singleton::instance = NULL;//静态成员变量类外初始化

饿汉模式:静态初始化实例方式,在自己被加载时就将自己实例化,提前占用系统资源。

其可以保证线程安全性,因为静态实例初始化在程序开始进入主函数之前就由主线程以单线程方式完成了初始化,不必担心多线程问题。

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
33
34
35
36
37
38
39
40
41
42
class Singleton
{
private:
static const Singleton *instance;
Singleton()
{
}
public:
static const Singleton* GetInstance()
{
return instance;
}
static void DestroyInstance()
{
if (instance != NULL)
{

delete instance;
instance = NULL;
}
}
};

//进入主函数之前就完成了实例初始化,是线程安全的
const Singleton* Singleton::instance = new Singleton;

//客户端代码
int main()
{
const Singleton *s1 = Singleton::GetInstance();
const Singleton *s2 = Singleton::GetInstance();
//const Singleton *s2 = s1->GetInstance();

if (s1 == s2)
{
cout << "两个对象是相同的实例" << endl

}
Singleton::DestroyInstance();
return 0;

}