概念
Singleton是对全局变量的取代策略。
作用: 保证一个类只能有一个实例,并提供一个全局唯一的访问点。
仅有一个实例:通过类的静态成员变量来体现。
提供访问它的全局访问点:访问静态成员变量的静态成员函数来体现。
设计模式一书中给出一种很不错的实现,定义一个单例类,使用类的私有静态指针变量指向类的唯一实例,并用一个公有的静态方法获取该实例。
单例模式通过类本身来管理其唯一实例,这种特性提供了解决问题的方法。唯一的实例是类的一个普通对象,但设计这个类时,让它只能创建一个实例并提供对此实例的全局访问。唯一的实例类Singleton在静态成员函数中隐藏创建实例的操作。习惯上把这个成员函数叫做Instance(),它的返回值是唯一实例的指针。
单例类Singleton有以下特征:
它有一个指向唯一实例的静态指针,并且是私有的;
它有一个公有的函数,可以获取这个唯一的实例,并且在需要的时候创建该实例;
它的构造函数是私有的,这样就不能从别处创建该类的实例。
UML图:
在Singleton模式的结构图中可以看到,我们通过维护一个static的成员变量_instance来记录这个唯一的对象实例。通过提供一个staitc的接口Instance来获得这个唯一的实例。
代码如下:
Singleton.h
Singleton.cpp
test.cpp
运行结果:
Singleton不可以被实例化,因此我们将其构造函数声明为protected或者直接声明为private。
---
程序设计过程中,经常会有"只能创建一个实例"的需求。
为保证创建单一实例,必须确保程序中只调用new Class()
由于随着代码的复杂性的增加,对象单例性经常会被忽视,由于资源独占性等原因,经常会产生一些意想不到的问题。
为了更好地实现优美的代码设计,单例模式(Singleton)应运而生。
单例模式的定义是:保证一个类、只有一个实例存在,同时提供能对该实例加以访问的全局访问方法。单例模式是一种对象创建型模式,使用单例模式,可以保证为一个类只生成唯一的实例对象。也就是说,在整个程序空间中,该类只存在一个实例对象。
在 Singleton 模式的结构图中可以看到,我们通过维护一个 static 的成员变量来记录这个唯一的对象实例。
应用场景
在应用系统开发中,我们常常有以下需求:
在多个线程之间,比如初始化一个socket资源;
在整个程序空间使用全局变量,共享资源;
大规模系统中,为了性能考虑,需要节省对象的创建时间等等。
使用方法:
a. 构造函数私有化(设置为private)=》防止从类外调用构造函数,保证在任何情况下只生成一个实例;
b. 提供一个全局的静态方法GetInstance(全局访问点)=》便于提供从类外部获取单例类的唯一实例的方法;
c. 在类中定义一个静态指针,指向本类的变量的静态变量指针。
懒汉单例和饿汉单例多线程场景分析
1."懒汉"模式虽然有优点,但是每次调用GetInstance()静态方法时,必须判断NULL == m_instance,使程序相对开销增大;
2. 多线程中会导致多个实例的产生,从而导致运行代码不正确以及内存的泄露;
3.未提供释放资源的函数,存在内存泄漏问题。
由于C++中构造函数并不是线程安全的。C++中的构造函数简单来说分两步:
第一步:内存分配;
第二步:初始化成员变量;
由于多线程的关系,可能当我们在分配内存好了以后,还没来得急初始化成员变量,就进行线程切换,另外一个线程拿到所有权后,由于内存已经分配了,但是变量初始化还没进行,因此获取成员变量的相关值会发生不一致现象。