有时候,需要一些工具性质的类,基本不用存储太多的跟自身有关的数据,在这种情况下,每次都去new一个对象,即增加了开销并且让代码更冗余。
这个时候,只需要一个实例对象就可以。
如果采用全局或者静态变量的方式,会影响封装性,难以保证别的代码不会对全局变量造成影响。
一、单例模式:设计模式中最简单的形式之一。目的是使得类的一个对象成为系统中的唯一实例。要实现这一点,可以从客户端对其进行实例化开始。因此需要用一种只允许生成对象类的唯一实例的机制,“阻止”所有想要生成对象的访问。使用工厂方法来限制实例化过程。这个方法应该是静态方法(类方法),因为让类的实例去生成另一个唯一实例毫无意义。
单例就是该类只能返回一个实例。
单例所具备的特点:
1.私有化的构造函数
2.私有的静态的全局变量
3.公有的静态的方法
单例分为懒汉式、饿汉式和双层锁式
1.懒汉式:
以时间换空间的方式。
第一次需要使用的时候才创建实例,定义了静态成员对象指针变量,程序运行之初分配空间,但是那个是指针的空间,不是对象的空间,所以不会调用对象的构造函数,而只有调用getinstance进行new操作的时候,才会对其调用构造函数,比较懒惰,所以叫懒汉模式。
注意:懒汉式有两个状态,单例未初始化和单例已经初始化。单例还未初始化时,如果有两个线程同时调用GetInstance方法,这时执行 m_pInstance == NULL 肯定为真,然后两个线程都初始化一个单例,最后得到的指针并不是指向同一个地方,不满足单例类的定义,所以饿汉式的写法会出现线程安全的问题。在多线程环境下,要对其进行修改,加锁。
2.饿汉式:
以空间换时间的方式。
一开始就创建了实例(静态对象),所以每次用到的之后直接返回静态对象地址。
/*
懒汉式:
缺点:
1.多线程的情况下可能会出现new两次的情况。
2.程序退出后没有运行析构函数。
*/
class CSingleton{
public:
static CSingleton* getinstance(){
if(m_instance=nullptr)
m_instance = new CSingleton();
return m_instance;
}
private:
CSingleton();
static CSingleton *m_instance;
};
//懒汉式多线程
//加锁即可,但是如果太多个线程同时查看锁状态可能会卡死,所以最后双层条件判断,先判断在查看锁状态,再判断。
class CSingleton{
public:
static CSingleton* getinstance(){
if(m_instance==nullptr){
lock();
if(m_instance==nullptr)
m_instance = new CSingleton();
unlock();
}
return m_instance;
}
private:
CSingleton();
static CSingleton* m_instance;
};
//饿汉式,静态对象方式
class CSingleton{
public:
static CSingleton* getinstance(){
static CSingleton instance;
return &instance;
}
private:
CSingleton();
~CSingleton();
};