单例设计模式
设计模式经典GoF定义的单例模式需要满足以下两个条件:
1、保证一个类只创建一个实例。
2、提供对该实例的全局访问点。
如果系统有类似的实体(有且只有一个,且需要全局访问),那么就可以将其实现为一个单例。
单例模式的优点:
1、在内存中只有一个对象,节省内存空间
2、避免频繁的创建销毁对象,可以提高性能
3、避免对共享资源的多重占用
4、可以全局访问
实际工作中常见的应用举例:
1、日志类,一个应用往往只对应一个日志实例。
2、配置类,应用的配置集中管理,并提供全局访问。
3、管理器,比如windows系统的任务管理器就是一个例子,总是只有一个管理器的实例。
4、共享资源类,加载资源需要较长时间,使用单例可以避免重复加载资源,并被多个地方共享访问。
实现一个简单的单例模式代码示例如下:
#include<iostream>
using namespace std;
mutex _mt;
class CSingleton {
private:
CSingleton() {
}
public:
static CSingleton * GetInstance() {
if (m_instance == nullptr) {
_mt.lock();
if (m_instance == nullptr){
m_instance = new CSingleton();
}
_mt.unlock();
}
return m_instance;
}
public:
static CSingleton * m_instance;
};
但是上述实现有个问题,返回的是指针,有可能被人为的delete掉,导致对象被提前销毁。还是建议使用返回引用的方式。
另外也可以使用static magic。如果当变量在初始化的时候,并发同时进入声明语句,并发线程将会阻塞等待初始化结束。这样可以保证并发线程在获取静态局部变量的时候一定是初始化过的,所以具有线程安全性。
#include <iostream>
using namespace std;
class CSingleton {
private:
CSingleton() {
cout << "CSingleton" << endl;
}
public:
~CSingleton() {
cout << "~CSingleton" << endl;
}
static CSingleton & GetInstance() {
static CSingleton _singleton;
/*
if (_singleton == nullptr) {
_mu.lock();
if (_singleton == nullptr) {
_singleton = new CSingleton();
}
_mu.unlock();
}
*/
return _singleton;
}
static CSingleton & _singleton;
};
int main() {
CSingleton& a = CSingleton::GetInstance();
CSingleton& b = CSingleton::GetInstance();
return 0;
}
执行结果是:
CSingleton
~CSingleton