单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例。
对于系统中的某些类来说,只有一个实例很重要,例如,一个系统中可以存在多个打印任务,但是只能有一个正在工作的任务;一个系统只能有一个窗口管理器或文件系统;一个系统只能有一个计时工具或ID(序号)生成器。如在Windows中就只能打开一个任务管理器。
如何保证一个类只有一个实例并且这个实例易于被访问呢?定义一个全局变量可以确保对象随时都可以被访问,但不能防止我们实例化多个对象。一个更好的解决办法是让类自身负责保存它的唯一实例。这个类可以保证没有其他实例被创建,并且它可以提供一个访问该实例的方法。这就是单例模式的模式动机。
显然单例模式的要点有三个;一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例。从具体实现角度来说,就是以下三点:一是单例模式的类只提供私有的构造函数,二是类定义中含有一个该类的静态私有对象,三是该类提供了一个静态的公有的函数用于创建或获取它本身的静态私有对象。
一、简单模式
#include "stdafx.h"
#include <iostream>
using namespace std;
/* 简单模式 */
class Singleton
{
public :
static Singleton* GetInstance( )// 获取对象单例的指针
{
if(m_singleton == NULL) // 如果单例对象没有创建, 则将其创建
{
m_singleton = new Singleton( );
}
return m_singleton;
}
static void DestroyInstance( ) // 销毁单例对象的空间
{
if(m_singleton != NULL)
{
delete m_singleton;
m_singleton = NULL;
}
}
private :
Singleton( )// 构造函数[被保护]
{
}
Singleton(const Singleton &singleton)// 赋值构造函数[被保护]
{
}
Singleton& operator = (const Singleton& rhs)
{
}
static Singleton *m_singleton;// 指向单例对象的指针
};
Singleton* Singleton::m_singleton = NULL; // 指向单例对象的指针
#include "stdafx.h"
#include <iostream>
#include <memory>
using namespace std;
/* 智能指针模式 */
class Singletonptr
{
public:
static Singletonptr* GetInstance()
{
if (pinstance.get()==NULL)
{
pinstance.reset(new Singletonptr);
}
return pinstance.get();
}
private:
Singletonptr(){}
~Singletonptr(){}
Singletonptr(const Singletonptr&){}
Singletonptr& operator = (const Singletonptr& rhs) {}
friend class auto_ptr<Singletonptr>;
static auto_ptr<Singletonptr> pinstance;
};
auto_ptr<Singletonptr> Singletonptr::pinstance;
三、线程安全模式
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
using namespace std;
/* 线程安全模式 */
CRITICAL_SECTION g_CS;
class Locker
{
public:
Locker()
{
InitializeCriticalSection(&g_CS);
}
~Locker()
{
DeleteCriticalSection(&g_CS);
}
void Lock()
{
EnterCriticalSection(&g_CS);
}
void UnLock()
{
LeaveCriticalSection(&g_CS);
}
};
Locker locker;
class Singletonsafe
{
public:
static Singletonsafe* GetInstance()
{
if (m_instancesafe==NULL)
{
locker.Lock();//上锁
if (m_instancesafe==NULL)
{
m_instancesafe=new Singletonsafe;
}
locker.UnLock();//解锁
}
return m_instancesafe;
}
static void DestroyInstance( ) // 销毁单例对象的空间
{
if(m_instancesafe != NULL)
{
delete m_instancesafe;
m_instancesafe = NULL;
}
}
private:
Singletonsafe(){}
Singletonsafe(const Singletonsafe& singletonsafe){}
Singletonsafe& operator = (const Singletonsafe& rhs) {}
~Singletonsafe(){}
private:
static Singletonsafe* m_instancesafe;
};
Singletonsafe* Singletonsafe::m_instancesafe=NULL;
四、模板模式
#include "stdafx.h"
#include <Windows.h>
#include <iostream>
using namespace std;
/* 模板模式 */
template<class T>
class SingletonT
{
public:
static T* GetInstance()
{
if (m_instanceT==NULL)
{
locker.Lock();
if (m_instanceT==NULL)
{
m_instanceT=new T;
}
locker.UnLock();
}
return m_instanceT;
}
static void DestroyInstance( ) // 销毁单例对象的空间
{
if(m_instanceT != NULL)
{
delete m_instanceT;
m_instanceT = NULL;
}
}
private:
SingletonT(){}
SingletonT(const SingletonT& singletonT){}
SingletonT & operator = (const SingletonT& singletonT){}
static T* m_instanceT;
};
template <class T>
T* SingletonT<T>::m_instanceT=NULL;
五、调用
int _tmain(int argc, _TCHAR* argv[])
{
//简单模式
Singleton *sp1 = Singleton::GetInstance( );
Singleton *sp2 = Singleton::GetInstance( );
std::cout <<(sp1 == sp2) <<std::endl;// 两个对象的地址是相同的
Singleton::DestroyInstance( );
//智能指针模式
Singletonptr* ps1=Singletonptr::GetInstance();
Singletonptr* ps2=Singletonptr::GetInstance();
if (ps1==ps2)
{
cout<<"p相等"<<endl;
}
//线程安全模式
Singletonsafe* s1=Singletonsafe::GetInstance();
Singletonsafe* s2=Singletonsafe::GetInstance();
if (s1==s2)
{
cout<<"s相等"<<endl;
}
Singletonsafe::DestroyInstance();
//模版模式
//调用方法很简单:
//1:用typedef申明一个变量名
typedef SingletonT<int> LISTEN;
//2:调用的地方写
LISTEN::GetInstance();
//3:关闭的地方写
LISTEN::DestroyInstance();
return 0;
}