上一篇讲了单例模式的基础使用,下面来看看单例模式更“高级”的使用方式。
宏定义实现:
如果使用之前的方式去实现单例类,就要为每一个类做相当繁琐的操作,而这些操作其实有很大一部分是高度类似的,我们没必要总是做这些无用功。
不妨,用两个宏来代替这些重复又高度类似的工作:
#include <mutex>
#include <memory>
#define SINGLETON_IMPLEMENT(ClassName) \
public: \
virtual ~ClassName(void) {}; \
static ClassName* GetInstance(); \
private: \
ClassName(void) {}; \
ClassName(const ClassName&); \
ClassName operator = (const ClassName&); \
static std::shared_ptr<ClassName> m_pInstance; \
static std::mutex m_mutex;
#define SINGLETON_DECLARE(ClassName) \
std::shared_ptr<ClassName> ClassName::m_pInstance; \
std::mutex ClassName::m_mutex; \
ClassName* ClassName::GetInstance() \
{ \
if (m_pInstance == NULL) \
{ \
std::unique_lock<std::mutex> lk(m_mutex); \
if (m_pInstance == NULL) \
m_pInstance = std::shared_ptr<ClassName>(new ClassName()); \
} \
return m_pInstance.get(); \
}
上面的代码实现了两个宏:SINGLETON_IMPLEMENT和SINGLETON_DECLARE。
不妨将上面的代码放到一个头文件里面,需要的时候包含进来。
这样,实现的一个单例类,只有3个非常简单的操作:
1、包含上面的代码(头文件)
2、在类声明里面使用SINGLETON_IMPLEMENT,参数为自身类名
3、在类外调用SINGLETON_DECLARE,参数为自身类名
就像这样:
#include "Singleton.h" //里面包含上述代码
class MyClass
{
SINGLETON_IMPLEMENT(MyClass)//类声明使用SINGLETON_IMPLEMENT
public:
void print() { cout << "I'm a singleton" << endl; }
};
SINGLETON_DECLARE(MyClass);//类外使用SINGLETON_DECLARE
int main()
{
MyClass::GetInstance()->print();
return 0;
}
只增加3行代码,就实现了一个单例类,是不是方便多了?
模板实现:
还有一种更灵活的方式,就是用模板实现单例:
#include <mutex>
#include <memory>
template <class T>
class Singleton
{
public:
static T* GetInstance()
{
if (_instance == NULL)
{
std::unique_lock<std::mutex> lk(_mutex);
if (_instance == NULL)
{
_instance = std::shared_ptr<T>(new T());
}
}
return _instance.get();
}
private:
Singleton();
~Singleton();
Singleton& operator=(const Singleton&);
Singleton(const Singleton&);
static std::mutex _mutex;
static std::shared_ptr<T> _instance;
};
template<class T>
std::mutex Singleton<T>::_mutex;
template<class T>
std::shared_ptr<T> Singleton<T>::_instance = NULL;
使用就更简单了,包含进来马上就可以用:
#include "Singleton.h"
class MyClass
{
public:
MyClass() {};
~MyClass() {};
void print() { cout << "I'm a singleton" << endl; }
};
int main()
{
Singleton<MyClass>::GetInstance()->print();
return 0;
}
模板方式虽然便捷,但是自定义的类本身却没有被限定不能被多次构造,这是一个弊端。
最后,附上完整代码:
http://pan.baidu.com/s/1bpKg50j