单件模式(Singleton Pattern)应该是设计模式中实现起来最简单的一个了。通过使用单件模式,能够保证全局只存在一个类的实例化对象。本文用C++语言来说明如何写一个简单的单件类。
在有些场景下需要一个类只能在全局存在一个实例化对象,典型的情况如线程池,数据库连接池,全局缓存,日志句柄等等。这种情况下如果实例化多个对象或是随意复制多份对象都会对全局共享的资源造成一定影响。单件设计模式就是为了解决这种问题产生的。
在C++中,要保证变量全局有效并且唯一可以使用static类型;另外想要禁止用户随意实例化类,可以将类的构造函数声明为private,同时也要禁止对象的复制和拷贝,同样将拷贝构造函数和赋值操作符声明为private。类的声明代码如下:
// Singleton.h
#ifndef __SINGLETON__
#define __SINGLETON__
class Singleton {
public:
static Singleton *getInstance();
private:
Singleton();
Singleton(const Singleton &s;);
void operator=(const Singleton &rhs;);
static Singleton *instance;
};
#endif
类的实现:
#include "Singleton.h"
Singleton * Singleton::instance = NULL;
Singleton::Singleton()
{
}
Singleton::Singleton(const Singleton &s;)
{
}
void Singleton::operator=(const Singleton &rhs;)
{
}
Singleton *Singleton::getInstance()
{
if (instance == NULL) {
instance = new Singleton;
}
return instance;
}
当需要类的实例化对象时,调用Singleton::getInstance()获得一个指向Singleton对象的指针。在getInstance()内部,首先判断类的成员变量instance是否为空。为空则表示这个类还没有实例化过,使用new来初始化;若instance不为空,则直接返回instance即可。
进一步可以将上述代码稍微改造一下,写成其他类可以复用的模板类,这样当任何一个类需要利用单件模式的特性时,都可以直接使用模板而不用再将上述框架实现一遍。代码如下:
// Singleton.h
#ifndef __SINGLETON__
#define __SINGLETON__
template
class Singleton {
public:
static T *getInstance()
{
if (instance == NULL) {
instance = new T;
}
return instance;
}
private:
Singleton(){};
Singleton(const Singleton &s;){};
void operator=(const Singleton &rhs;){};
static T *instance;
};
template T * Singleton::instance = NULL;
#endif
最后一个问题,上述代码并不是线程安全的!原因在于getInstance()函数中在判断instance是否为空时没有进行线程同步保护。最简单的办法就是在getInstance()中加上互斥锁。当然加锁肯定会带来性能开销。