一、什么是单例模式
只能创建出一个类对象(只有一个实际的实例)的叫做单例模式。
注意:
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
从具体实现角度来讲就是三点:
1、单例模式的类只提供私有的构造函数。
2、类定义中含有一个该类的静态私有对象。
3、该类提供了一个静态的公有的函数用于创建或获取它本身的静态私有对象。
C++如何实现单例:
1、禁止类的外部创建类对象:构造函数设置成私有。
2、类自己维护一个唯一的对象:使用静态指针指向。
3、提供一个获取实例的方法:静态成员函数获取静态指针。
二、为什么使用单例模式
对于系统中的某些类来说,只有一个实例很重要,例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务;一个系统只能有一个窗口管理器或文件系统;一个系统只能有一个计时工具或ID(序号)生成器。如在Windows中就只能打开一个任务管理器。如果不使用机制对窗口对象进行唯一化,将弹出多个窗口,如果这些窗口显示的内容完全一致,则是重复对象,浪费内存资源;如果这些窗口显示的内容不一致,则意味着在某一瞬间系统有多个状态,与实际不符,也会给用户带来误解,不知道哪一个才是真实的状态。因此有时确保系统中某个对象的唯一性即一个类只能有一个实例非常重要。
三、单例模式的应用场景
1、Window系统的任务管器
2、Linux/Unix系统的日志系统
3、网站的访问计数器
4、服务端程序的连接池、线程池、数据池。
四、饿汉模式
饿汉模式:将单例类的唯一实例对象定义为成员变量,当程序开始运行,实例对象就已经创建完成。
优点:加载进行时静态创建单例对象,线程安全。
缺点:无论使用与否,总要创建,浪费内存。
class Singleton
{
private:
Singleton(void) { }
static Singleton object;
public:
static Singleton& get_object(void)
{
return object;
}
};
Singleton Singleton::object;
五、懒汉模式
用静态成员指针来指向单例类的唯一实例对象,只有真正调用获取实例对象的静态接口时,实例对象才被创建。
优点:什么时用什么时候创建,节约内存。
缺点:在第一调用访问获取实例对象的静态接口才真正创建,如果在多线操作情况下有可能被创建出多个实例对象(虽然可能性很低),存在线程不安全问题。
class Singleton
{
private:
Singleton(void) { }
static Singleton* objectp;
public:
static Singleton& get_object(void)
{
if(NULL == objectp)
{
objectp = new Singleton;
}
return *objectp;
}
};
Singleton* Singleton:: objectp;
六、加锁的懒汉模式
相对普通的懒汉模式加锁的懒汉模式能在多线程中很好的工作,但是,效率很低,加锁会影响效率,而且大部分情况下不需要加锁。
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
class Singleton
{
private:
Singleton(void) { }
static Singleton* objectp;
public:
static Singleton& get_object(void)
{
if(NULL == objectp)
{
pthread_mutex_lock(&mutex);
objectp = new Singleton;
pthread_mutex_unlock(&mutex);
}
return *objectp;
}
};
Singleton* Singleton:: objectp;