单例模式的功能——取代全局变量,来实现共享,实战是全局配置文件
,不需要每次使用这个文件的时候都读
这个文件。(因为n多个地方都需要用这个配置文件,单例模式让它只读一次就可以了,接下来使用这个全局配置文件的时候,就会方便很多)
- 之所以要使用static,是因为构造器和析构器都是private的,不能再通过【创建类对象的方式】访问类内部的东西了,因此只能通过
static
的方式。
创建类对象的方式一般有2种,第一种是
A a
,第二种是new A
一、普通的单例模式(懒汉)
- 第一次用到
类实例
的时候才去实例化
#include <iostream>
using namespace std;
class Singleton
{
public:
static Singleton* getInstance()
{
if (_ins == nullptr) _ins = new Singleton;
return _ins;
}
private:
static Singleton * _ins;
Singleton() {}
Singleton(const Singleton&) {}
Singleton& operator=(const Singleton&) {}
~Singleton() {}
};
Singleton* Singleton::_ins = nullptr;
int main()
{
// Singleton a;
Singleton *ps = Singleton::getInstance();
Singleton *ps2 = Singleton::getInstance();
if (ps == ps2) cout << "ps == ps2" << endl;
return 0;
}
二、饿汉的单例模式(线程安全)
- 单例类的
定义
的时候就进行实例化
#include <iostream>
using namespace std;
class Singleton
{
public:
static Singleton* getInstance()
{
return _ins;
}
private:
static Singleton * _ins;
Singleton() {}
Singleton(const Singleton&) {}
Singleton& operator=(const Singleton&) {}
~Singleton() {}
};
// 初始化
Singleton* Singleton::_ins = new Singleton();
int main()
{
// Singleton a;
Singleton *ps = Singleton::getInstance();
Singleton *ps2 = Singleton::getInstance();
if (ps == ps2) cout << "ps == ps2" << endl;
return 0;
}
三、线程安全的懒汉模式——多线程加锁
- 懒汉模式的基础上,在判断
对象_ins
是否是null前,加了一个锁
if (_ins == nullptr)
是一个【读操作】
性能差是因为每次不管哪个线程调用getInstance()
都会执行一次加锁和释放锁
。
#include <iostream>
#include <mutex>
using namespace std;
class Singleton
{
private:
static Singleton * _ins;
static mutex _lock;
static mutex lock_;
Singleton() {}
Singleton(const Singleton&) {}
Singleton& operator=(const Singleton&) {}
~Singleton() {}
public:
static Singleton* getInstance()
{
lock_guard<mutex> guard(_lock);
if (_ins == nullptr) _ins = new Singleton();
return _ins;
}
};
// 初始化
Singleton* Singleton::_ins = nullptr;
int main()
{
return 0;
}
四、线程安全的懒汉模式——双重检查锁+垃圾回收
#include <iostream>
#include <mutex>
using namespace std;
class Singleton
{
private:
static Singleton * _ins;
static mutex _lock;
Singleton() {}
Singleton(const Singleton&) {}
Singleton& operator=(const Singleton&) {}
~Singleton() {}
public:
static Singleton* getInstance()
{
if (_ins == nullptr)
{
lock_guard<mutex> guard(_lock);
if (_ins == nullptr) _ins = new Singleton();
//_ins = new Singleton();
}
return _ins;
}
class CGarbo
{
public:
~CGarbo()
{
if (Singleton::_ins) delete Singleton::_ins;
}
};
static CGarbo garbo;
};
// 初始化
Singleton* Singleton::_ins = nullptr;
Singleton::CGarbo garbo;
int main()
{
return 0;
}
五、单例模式的实战
- 自定义一个
数据文件com.cof
- 有3个类A, B, C同时调用
Config生成对象
- 得到的数据是一样的,相当于
单例完成了全局变量
的工作,但是单例比全局变量好——
图解
单例不需要销毁,因为单例只会产生一个对象, 在程序结束的时候就会销毁。
网友评论