0%

单例模式C++

单例模式

保证类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享

单例模式的要点有三个:

  1. 单例类只能有一个实例
  2. 必须自行创建这个实例
  3. 必须自行向整个系统提供这个实例

注意点

  1. 实例控制: 单例模式会阻止其他对象实例化自己的单例对象的副本,从而确保所有对象都访问唯一实例
  2. 灵活性: 因为类控制实例化过程,所以类可以灵活更改实例化过程
  3. 开销: 虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销,这个问题可以通过静态初始化解决此问题。定义一个私有的静态指针instance,和一个公有的静态函数 GetInstance()。

优点:

  1. 在内存中只有一个对象,节省内存空间
  2. 避免频繁的创建销毁对象,可以提高性能
  3. 避免对共享资源的多重占用
  4. 可以全局访问

适用场景:

  1. 需要频繁实例化然后销毁的对象
  2. 创建对象耗时过多或者耗资源过多,但又经常用到的对象
  3. 有状态的工具类对象
  4. 频繁访问数据库或文件的对象
  5. 以及其他要求只有一个对象的场景

    懒汉

    故名思义,不到万不得已就不会去实例化类,也就是说在第一次用到类实例的时候才会去实例化

在访问量较小时,采用懒汉实现。这是以时间换空间

经典懒汉

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Singleton{
public:
static Singleton* GetInstance();
private
Singleton(){};
Singleton(const Singleton&){};//禁止拷贝
Singleton& operator = (const Singleton&){};//禁止赋值

static Singleton* instance;
};
//初始化
Singleton* Singleton::instance = NULL;
Singleton* Singleton::GetInstance(){
if(instance == NULL){
instance = new Singleton();
}
return instance;
}

懒汉模式下,在定义instance变量时先等于NULL,在调用GetInstance()方法时,再判断是否要赋值。这种模式,并非是线程安全的,因为多个线程同时调用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
class Singleton
{
private:
Singleton(){
pthread_mutex_init(&mutex);
};
Singleton(const Singleton&){};
Singleton& operator=(const Singleton&){};
static Singleton* instance;
public:
static pthread_mutex_t mutex;
static Singleton* GetInstance();
};

pthread_mutex_t Singleton::mutex;
Singleton* Singleton::instance = NULL;

Singleton* Singleton::GetInstance(){
if(instance == NULL){
pthread_mutex_lock(&mutex);
if(instance == NULL)
instance = new Singleton();
pthread_mutex_unlock(&mutex);
}
return instance;
}

饿汉

线程安全:还未使用变量时,已经对instance进行赋值,就像很饥饿的感觉。在多线程环境下肯定是线程安全的,因为不存在多线程实例化的问题。

饿了肯定要饥不择食,所以在单例类定义的时候就进行实例化

由于要进行线程同步,所以在访问量比较大,或者可能访问的线程比较多时,采用饿汉实现,可以实现更好的性能。这是以空间换时间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Singleton{
public:
static Singleton* GetInstance();
private:
Singleton(const Singleton&){};
Singleton& operator=(const Singleton&){};
Singleton(){};
static Singleton* instance;
};

Singleton* Singleton::instance = new Singleton();
Singleton* Singleton::GetInstance(){
return instance;
}