一、定义
单例模式,保证一个类仅有一个实例,并提供一个访问它的全局访问点。
顾名思义,就是只能有一个实例,必须保证:
(1)该类不能被复制
(2)该类不能被公开的创造
二、结构图
1.Singleton类,定义一个GetInstance操作,允许客户访问它的唯一实例,GetInstance是一个静态方法,主要负责创建自己的唯一实例。
2.单例模式严格地控制客户怎样访问它以及何时访问它,实现对唯一实例的受控访问。
三、例子
那么对于C++来说,它的构造函数,拷贝构造函数和他的赋值函数都不能被公开调用。
但对于该私有的构造函数的构造时机上来说也可以分两种情况来构造:
(1)只有当需要改类的时候去构造(即为懒汉模式)
(2)在程序开始之前就先构造好,到时候直接调用就可以(即为饿汉模式)
1. 懒汉模式:
class single1
{
public:
static single1& getInstance()
{
static single1 instance;
return instance;
}
private:
single1(){};
single1(const single1&);
single1& operator=(const single1&);
};
2.饿汉模式:
class single2
{
public:
static single2* getInstance()
{
return mInstance;
}
private:
static single2* mInstance;
single2(){};
single2(const single2&);
single2& operator=(const single2&);
};
single2* single2::mInstance = new single2;
备注:运用静态局部变量和静态实例的特性,使得我们的这两种模式都适用于多线程。
3.最简单的单例模式(不考虑并发访问)
class Singleton {
private:
static Singleton singleton; //一个静态的实例
Singleton(){}
public:
//给出一个公共的静态方法返回一个单一实例
public static Singleton getInstance(){
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
说明:
(1) 静态实例,带有static关键字的属性在每一个类中都是唯一的。
(2) 限制客户端随意创造实例,即私有化构造方法,此为保证单例的最重要的一步。
(3) 给一个公共的获取实例的静态方法,注意,是静态的方法,因为这个方法是在我们未获取到实例的时候就要提供给客户端调用的,所以如果是非静态的话,那就变成一个矛盾体了,因为非静态的方法必须要拥有实例才可以调用。
(4) 判断只有持有的静态实例为null时才调用构造方法创造一个实例,否则就直接返回。
4.避免并发产生问题,使用双重加锁
class Singleton {
private:
Singleton(){}
static class SingletonInstance{
static Singleton instance = new Singleton();
}
public:
static Singleton getInstance(){
return SingletonInstance.instance;
}
}
说明:
(1)Singleton最多只有一个实例,在不考虑反射强行突破访问限制的情况下。
(2)保证了并发访问的情况下,不会发生由于并发而产生多个实例。
(3)保证了并发访问的情况下,不会由于初始化动作未完全完成而造成使用了尚未正确初始化的实例。
四、适用性
1.应用中有对象需要是全局的且唯一。
2.一个对象在应用中出现多个实例是否会引起逻辑上或者是程序上的错误。
五、优点
1.尽可能的节约内存空间,减少无谓的GC(垃圾回收:自动回收内存),并且使应用可以正常运行。
2.比如配置文件信息的类
六、缺点
1.在以为是单例的情况下,却产生了多个实例,例如多线程未加锁