单例模式是很常用的设计模式,如果希望系统中某个类的对象只能有一个或者有一个就够了,那么便可以采用单例模式来解决。
下面用C++实现一个单例模板类,那么其他的类只需继承它,便可以成为单例类。
本例中使用了 CMutex类,是考虑多线程的情况,这个类的定义请参见笔者的另一篇博客《C++简单封装互斥量》,
下面用C++实现一个单例模板类,那么其他的类只需继承它,便可以成为单例类。
本例中使用了 CMutex类,是考虑多线程的情况,这个类的定义请参见笔者的另一篇博客《C++简单封装互斥量》,
链接 http://blog.csdn.net/kentzhang_/article/details/48180865
代码如下:
BaseSingleton.h
/*************************************************************************
> File Name: BaseSingleton.h
> Author: KentZhang
> Mail: zhchk2010@qq.com
> Created Time: Wed 04 Sep 2015 09:02:12 PM CST
************************************************************************/
#ifndef __BASE_SINGLETON_H__
#define __BASE_SINGLETON_H__
#include<new>
#include "CMutex.h"
template<typename T>
class BaseSingleton
{
public:
static T *Instance()
{
if(NULL != m_Instance)
{
return m_Instance;
}
m_Mutex.Lock();
if(NULL != m_Instance)
{
m_Mutex.UnLock();
return m_Instance;
}
m_Instance = new(std::nothrow) T();
m_Mutex.UnLock();
return m_Instance;
}
BaseSingleton(){}
virtual ~BaseSingleton(){}
private:
static T *m_Instance;
static CMutex m_Mutex;
};
template<typename T>
T *BaseSingleton<T>::m_Instance = NULL;
template<typename T>
CMutex BaseSingleton<T>::m_Mutex;
#endif
测试用例:
TestSingleton.cpp
/*************************************************************************
> File Name: TestSingleton.cpp
> Author: KentZhang
> Mail: zhchk2010@qq.com
> Created Time: Wed 04 Sep 2015 09:21:10 PM CST
************************************************************************/
#include "BaseSingleton.h"
#include <string>
#include <iostream>
class TestSingleton : public BaseSingleton<TestSingleton>
{
private:
TestSingleton(){}; //构造函数,拷贝构造函数,声明为私有,不允许在类外创建对象,保证该类只有一个对象
TestSingleton(const TestSingleton&){};
public:
~TestSingleton(){};
void Show(){std::cout<<"I am a singleton."<<std::endl;};
friend BaseSingleton<TestSingleton>; //由于构造函数为私有,而基类必须调用,所以这里声明基类为友元类
};
int main()
{
//TestSingleton ts; //这里编译报错,显然是不允许在类外创建对象
TestSingleton* p1 = TestSingleton::Instance();
p1->Show();
std::cout<<"p1="<<p1<<std::endl;
//TestSingleton ts(*p1); //这种方式,同样报错
TestSingleton* p2 = TestSingleton::Instance();
p2->Show();
std::cout<<"p2="<<p2<<std::endl;
TestSingleton* p3 = TestSingleton::Instance();
p3->Show();
std::cout<<"p3="<<p3<<std::endl;
return 0;
}
编译:g++ CMutex.cpp TestSingleton.cpp -lpthread -o main
执行:./main
I am a singleton.
p1=0x82ad028
I am a singleton.
p2=0x82ad028
I am a singleton.
p3=0x82ad028
在本例中,有个明显的缺陷,即那个静态的单例指针才会何时delete,当然delete会自动调用它的析构函数完成终止化操作。
如果手动判断delete,但是在大多时候,并不能准确的判断单例何时不再使用,另一方面的单例类在内存中只有一个对象,
并不会造成内存泄露,因此大多数时候单例对象的析构是在程序结束的时候完成的。
上面的单例对象是在堆上分配的,需要手动delete,下面采用在静态区分配对象,单例基类修改如下:
BaseSingleton.h
#ifndef __BASE_SINGLETON_H__
#define __BASE_SINGLETON_H__
#include<new>
#include "CMutex.h"
template<typename T>
class BaseSingleton
{
public:
static T *Instance()
{
if(NULL != m_Instance)
{
return m_Instance;
}
m_Mutex.Lock();
if(NULL != m_Instance)
{
m_Mutex.UnLock();
return m_Instance;
}
//m_Instance = new(std::nothrow) T();
static T tInstance; //这里采用静态局部变量,保证程序运行时一直存在,程序结束时,会自动析构这个静态变量
m_Instance = &tInstance;
m_Mutex.UnLock();
return m_Instance;
}
BaseSingleton(){}
virtual ~BaseSingleton(){}
static T *m_Instance;
static CMutex m_Mutex;
};
template<typename T>
T *BaseSingleton<T>::m_Instance = NULL;
template<typename T>
CMutex BaseSingleton<T>::m_Mutex;
#endif
由于笔者的水平有限,出错在所难免,恳请读者拍砖指正,谢谢阅读。