单例设计模式
什么时候使用单例?
单例模式是一个经典的设计模式,在需要全进程唯一实例时,往往会使用单例模式进行设计
1、唯一数据入口
2、共用的资源
3、唯一的控制者
4、如果任何实例,只希望一个进程只有一个,那么使用单例吧
什么时候不能使用单例?
1、实例的功能不确定
2、依附于其他的对象或线程
3、只有一个对象会带来性能上的明显下降
4、其他可能需要创建对个实例的情况
单例设计模式分为:懒汉模式和饿汉模式
懒汉:故名思义,不到万不得已就不会去实例化类,也就是说在第一次用到类实例的时候才会去实例化,所以上边的经典方法被归为懒汉实现;
饿汉:饿了肯定要饥不择食。所以在单例类定义的时候就进行实例化。
线程安全
懒汉模式需要注意加锁;
饿汉模式本身就是线程安全的,饿汉模式的单例static的成员是在类加载的时候就生成了,而不是生成对象的时候因此线程是安全的。
特点与选择:
由于要进行线程同步,所以在访问量比较大,或者可能访问的线程比较多时,采用饿汉实现,可以实现更好的性能。这是以空间换时间。
在访问量较小时,采用懒汉实现。这是以时间换空间。
代码:
C++单例封装头文件:
#pragma once
#include <stdlib.h>
#include <pthread.h>
template <typename T>
class Singleton
{
public:
static T &instance()
{
_init();
return *_instance;
}
static void destroy()
{
if (0 == _instance) {
return;
}
pthread_mutex_lock(&_mutex);
if (0 != _instance) {
delete _instance;
_instance = 0;
}
pthread_mutex_unlock(&_mutex);
}
private:
static void _init()
{
if (0 != _instance) {
return;
}
pthread_mutex_lock(&_mutex);
if (0 == _instance) {
_instance = new T; // 类型T需提供默认构造函数
// atexit(destroy); // 程序结束时调用注册的函数
}
pthread_mutex_unlock(&_mutex);
}
Singleton();
~Singleton();
Singleton(const Singleton &other);
Singleton &operator=(const Singleton &other);
static T *_instance;
static pthread_mutex_t _mutex;
};
template <typename T>
T * Singleton <T>::_instance = 0;
template <typename T>
pthread_mutex_t Singleton<T>::_mutex = PTHREAD_MUTEX_INITIALIZER;
懒汉模式代码:
用例为QT开发环境
#ifndef TESTCLASS
#define TESTCLASS
#pragma once
#include "Singleton.h"
class TestClass : public QWidget {
Q_OBJECT
public :
TestClass(QWidget *parent = NULL);
~TestClass();
private:
};
typedef Singleton<TestClass> TestClassManager;
#define testClassMgr TestClassManager::instance()
#endif // HOTKEYMANAGER
饿汉模式代码:
class singleton
{
protected:
singleton()
{}
private:
static singleton* p;
public:
static singleton* initance();
};
singleton* singleton::p = new singleton;
singleton* singleton::initance()
{
return p;
}