单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
单例模式分为懒汉式和饿汉式
懒汉式是当该实例第一次被引用时,才将自己实例化;
饿汉式是在被加载时就将自己实例化了。
懒汉式
class Singleton{
public:
static Singleton* getInstance();
void doSomething();
void destroy();
private:
Singleton();
~Singleton();
Singleton(const Singleton&);
Singleton& operator = (const Singleton&);
static Singleton* instance;
};
Singleton* Singleton::instance = NULL;
Singleton::Singleton() {}
Singleton::~Singleton() {}
Singleton* Singleton::getInstance() {
if(instance == NULL)
instance = new Singleton();
return instance;
}
void Singleton::destroy() {
delete this;
instance = NULL;
}
int main() {
Singleton::getInstance()->doSomething();
Singleton::getInstance()->destroy();
return 0;
}
懒汉式是线程不安全的,当单例模式应用在多线程中,应该使用锁进行同步
class Singleton{
public:
static Singleton* getInstance();
void doSomething();
void destroy();
private:
Singleton();
~Singleton();
Singleton(const Singleton&);
Singleton& operator = (const Singleton&);
static Singleton* instance;
};
Singleton* Singleton::instance = NULL;
Singleton::Singleton() {}
Singleton::~Singleton() {}
Singleton* Singleton::getInstance() {
if(instance == NULL) {
lock();
if(instance == NULL)
instance = new Singleton();
unlock();
return instance;
}
void Singleton::destroy() {
delete this;
instance = NULL;
}
int main() {
Singleton::getInstance()->doSomething();
Singleton::getInstance()->destroy();
return 0;
}
而饿汉式是线程安全的
class Singleton{
public:
static Singleton* getInstance();
void doSomething();
void destroy();
private:
Singleton();
~Singleton();
Singleton(const Singleton&);
Singleton& operator = (const Singleton&);
static Singleton* instance;
};
Singleton* Singleton::instance = new Singleton();
Singleton::Singleton() {}
Singleton::~Singleton() {}
Singleton* Singleton::getInstance() {
return instance;
}
void Singleton::destroy() {
delete this;
instance = NULL;
}
int main() {
Singleton::getInstance()->doSomething();
Singleton::getInstance()->destroy();
return 0;
}
优缺点
饿汉式
优点
1. 线程安全
2. 在类加载的同时已经创建好一个静态对象,调用时反应速度快
缺点
资源效率不高,可能getInstance()永远不会执行到,但执行该类的其他静态方法,那么这个实例仍然初始化
懒汉式
优点:
避免了饿汉式的那种在没有用到的情况下创建事例,资源利用率高,不执行getInstance()就不会被实例,可以执行该类的其他静态方法。
缺点:
不是线程安全,在多线程中需要线程同步,同步加锁的过程提高了系统的开销
应用场景
- 网站的计数器,一般也是采用单例模式实现,否则难以同步。
- 应用程序的日志应用,一般都何用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作,否则内容不好追加。
- Web应用的配置对象的读取,一般也应用单例模式,这个是由于配置文件是共享的资源。
- 数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。数据库软件系统中使用数据库连接池,主要是节省打开或者关闭数据库连接所引起的效率损耗,这种效率上的损耗还是非常昂贵的,因为何用单例模式来维护,就可以大大降低这种损耗。
- 多线程的线程池的设计一般也是采用单例模式,这是由于线程池要方便对池中的线程进行控制。
- 操作系统的文件系统,也是大的单例模式实现的具体例子,一个操作系统只能有一个文件系统。