一 简介
一个类只能创建一个对象,即单例模式,该模式可以保证系统中该类只有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息,这种方式简化了在复杂环境下的配置管理。
二 两种方式
单例两种实现方法:饿汉与懒汉。
饿汉:饿了肯定要饥不择食。所以在单例类定义的时候就进行实例化。
懒汉:故名思义不到万不得已就不会去实例化类,也就是说在第一次用到类实例的时候才会去实例化.内部静态变量的懒汉实现,在instance函数里定义一个静态的实例,在返回时只需要返回其指针就可以了。
三 例子
方式一(饿汉模式)
不管你将来用不用,程序启动时就创建一个唯一的实例对象
class Singleton
{
public:
static Singleton * getInstance();
private:
Singleton() { cout << "Create Singleton" << endl; };
//防拷贝
Singleton(const Singleton& s) = delete;
Singleton& operator=(const Singleton& s) = delete;
static Singleton * m_singleton;
};
//饿汉单例,即在最开始的时候,静态对象就已经创建完成;
Singleton *Singleton::m_singleton = new Singleton();
Singleton * Singleton::getInstance()
{
return m_singleton;
}
优点: 实现简单, 多线程情景下效率高
缺点: 程序启动慢, 多个单例对象初始化的顺序无法控制
方式二(懒汉模式)
#include <mutex>
class Singleton
{
public:
static Singleton * getInstance();
private:
Singleton() {cout << "Create Singleton" << endl; };
//防拷贝
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
static Singleton * m_singleton;
static mutex m_mutex;
};
Singleton * Singleton::m_singleton = nullptr;
mutex Singleton::m_mutex;
Singleton * Singleton::getInstance()
{
//考虑两个线程同时首次调用getInstance方法且同时检测到m_singleton是NULL值,
//则两个线程会同时构造一个实例给m_singleton,这是严重的错误,要加锁!!!
if(m_singleton)
return m_singleton;
m_mutex.lock();
if (nullptr == m_singleton)
//第一次调用,创建对象
m_singleton = new Singleton();
m_mutex.unlock();
return m_singleton;
}
优点:第一次使用实例对象时,创建对象。进程启动无负载。多个单例实例启动顺序自由控制。
缺点:复杂
四 特点与选择:
由于要进行线程同步,所以在访问量比较大,或者可能访问的线程比较多时,采用饿汉实现,可以实现更好的性能。这是以空间换时间。
在访问量较小时,采用懒汉实现。这是以时间换空间。