简述
单例,顾名思义,就是一个程序中,只能存在一个这样的实例。所以要实现单例必须
- 私有化构造函数,禁止外部创建新的对象
- 私有化析构函数,防止资源不正确释放
- 私有化拷贝构造函数,禁止拷贝出新的对象
- 私有化赋值运算符,禁止通过赋值创建出新的对象
- 提供获取实例的方法
- 提供销毁实例的方法
简单实现
#include <iostream>
class Singleton
{
Singleton()
{
std::cout << "creator object" << std::endl;
}
~Singleton()
{
std::cout << "destroy object" << std::endl;
}
public:
static Singleton *Instance()
{
if(!self) {
self = new Singleton;
}
return self;
}
void destroy()
{
if(self) {
delete self;
self = NULL;
}
}
void dosomething()
{
std::cout << "do something" << std::endl;
}
private:
static Singleton *self;
Singleton(const Singleton &);
Singleton &operator = (const Singleton &);
};
Singleton *Singleton::self = NULL;
单例实现好了,来应用
int main(int , char *[])
{
Singleton *obj = Singleton::Instance();
obj->dosomething();
obj->destroy();
return 0;
}
输出
creator object
do something
destroy object
无异常,但每次都需要在程序结束前手动删除,可能会不小心漏了, 所以需要增加一个自动释放资源的类。
在Singleton
中增加嵌套类GC
用于垃圾回收,由于嵌套类GC
使用了Singleton
中的私有静态成员变量,所以GC
也必须私有化,防止在类外创建
class GC
{
public:
GC() { }
~GC()
{
if (self) {
delete self;
self = NULL;
}
}
};
修改获取实例的方法
static Singleton *Instance()
{
if(!self) {
static GC gc;
self = new Singleton;
}
return self;
}
使用
int main(int , char *[])
{
Singleton*obj = Singleton::Instance();
obj->dosomething();
return 0;
}
输出
creator object
do something
destroy object
这样程序关闭时,就会自动释放单例资源。
完整代码
#include <iostream>
class Singleton
{
Singleton()
{
std::cout << "creator object" << std::endl;
}
~Singleton()
{
std::cout << "destroy object" << std::endl;
}
public:
static Singleton *Instance()
{
if(!self) {
static GC gc;
self = new Singleton;
}
return self;
}
void destroy()
{
if(self) {
delete self;
self = NULL;
}
}
void dosomething()
{
std::cout << "do something" << std::endl;
}
private:
static Singleton *self;
Singleton(const Singleton &);
Singleton &operator = (const Singleton &);
class GC
{
public:
GC() { }
~GC()
{
if (self) {
delete self;
self = NULL;
}
}
};
};
Singleton *Singleton::self = NULL;
int main(int , char *[])
{
Singleton *obj = Singleton::Instance();
obj->dosomething();
return 0;
}
单例工厂
有时候一个程序中存在大量单例,每个单例都需要重新实现这些方法,有没有方法可以把这些重复的部分复用起来呢?
创建工厂
#include <QMutex>
template <typename T>
class Factory
{
static QMutex mutex; //因为本人使用Qt,所以使用Qt 自带的锁,其他平台可以自行换成各平台适用的锁
static T *singleton;
public:
static T *Instance()
{
if(!singleton) {
QMutexLocker clocker(&mutex);//上锁,超出作用域后, QMutexLocker 的对象会在析构时自动解锁
if(!singleton) {
static GC gc;
singleton = new T;
}
}
return singleton;
}
private:
Factory() {} //禁止构造,禁止继承
class GC
{
public:
GC() { }
~GC()
{
if (singleton) {
delete singleton;
singleton = NULL;
}
}
};
};
template <class T>
T *Factory<T>::singleton = NULL;
template <class T>
QMutex Factory<T>::mutex;
创建需要单例化的类
class Object
{
friend class Factory<Object>;
Object()
{
std::cout << "creator object" << std::endl;
}
~Object()
{
std::cout << "destroy object" << std::endl;
}
Object(const Object &);
Object &operator = (const Object &);
public:
void dosomething()
{
std::cout << "do something" << std::endl;
}
Object *Instance()
{
return Factory<Object>::Instance();
}
};
本类私有化了构造函数和析构函数,声明了友元类Factory<Object>
, 并将其重命名为 Singleton
下面看使用方法
int main(int , char *[])
{
Object::Instance()->dosomething();
return 0;
}
输出
creator object
do something
destroy object
当然,模板单例还可以使用继承的方法,继承模板,实现模板单例,但这里我将模板的构造函数私有化了,使其不可被继承。
想要使用继承的方法实现模板单例,网上很多,这里就不再过多赘述了。