一、用模板实现单例模式
在前面的文章中,用过多种方法实现单例模式,现在用模板方式来实现:
为了实现线程安全,需要在linux 下使用pthread_mutex_t 加锁,请使用g++ 编译并需要链接 -lpthread
使用的是double-check lock, 指针instance_ 最好声明为volatile,防止优化。
Singleton.h:
/*************************************************************************
> File Name: Singleton.h
> Author: Simba
> Mail: dameng34@163.com
> Created Time: Wed 02 Apr 2014 01:33:39 AM PDT
************************************************************************/
#ifndef _SINGLETON_H_
#define _SINGLETON_H_
#include <iostream>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
using namespace std;
template < typename T > class Singleton
{
public:
static T &GetInstance()
{
Init();
return *instance_;
}
private:
static void Init()
{
if (instance_ == 0)
{
pthread_mutex_lock(&g_mutex);
if (instance_ == 0)
{
instance_ = new T;
atexit(Destroy); //程序结束时调用注册的函数
}
pthread_mutex_unlock(&g_mutex);
}
}
static void Destroy()
{
delete instance_;
}
Singleton(const Singleton &other);
Singleton &operator=(const Singleton &other);
Singleton();
~Singleton();
static T * volatile instance_;
static pthread_mutex_t g_mutex;
};
template < typename T >
T * volatile Singleton < T >::instance_ = 0;
template < typename T >
pthread_mutex_t Singleton<T> ::g_mutex = PTHREAD_MUTEX_INITIALIZER;
#endif // _SINGLETON_H_
main.cpp:
/*************************************************************************
> File Name: main.cpp
> Author: Simba
> Mail: dameng34@163.com
> Created Time: Wed 02 Apr 2014 01:30:13 AM PDT
************************************************************************/
#include "Singleton.h"
class ApplicationImpl
{
public:
ApplicationImpl()
{
cout << "ApplicationImpl ..." << endl;
}
~ApplicationImpl()
{
cout << "~ApplicationImpl ..." << endl;
}
void Run()
{
cout << "Run ..." << endl;
}
};
typedef Singleton < ApplicationImpl > Application;
void *routine(void *arg)
{
Application::GetInstance().Run();
}
int main(void)
{
Application::GetInstance().Run();
pthread_t tid;
int ret;
if ((ret = pthread_create(&tid, NULL, routine, NULL)) != 0)
{
fprintf(stderr, "pthread create: %s\n", strerror(ret));
exit(EXIT_FAILURE);
}
Application::GetInstance().Run();
pthread_join(tid, NULL);
return 0;
}
即 将Singleton 实现为模板类,将ApplicationImpl 类包装成单例模式类,可以看到构造函数和析构函数都只调用了一次。程序使用一个小技巧,用axexit 函数注册了程序结束时需要调用的函数。
二、模板方式实现动态创建对象
在前面的文章曾经使用宏定义的方式实现动态创建对象,现在在 DynBase.h 中用模板类将宏定义替换掉,其他代码不变:
//class Register
//{
//public:
// Register(const string &name, CREATE_FUNC func)
// {
// DynObjectFactory::Register(name, func);
// }
//};
//
//#define REGISTER_CLASS(class_name) \
//class class_name##Register { \
//public: \
// static void* NewInstance() \
// { \
// return new class_name; \
// } \
//private: \
// static Register reg_; \
//}; \
//Register class_name##Register::reg_(#class_name, class_name##Register::NewInstance)
template <typename T>
class DelegatingClass
{
public:
DelegatingClass(const string &name)
{
DynObjectFactory::Register(name, &(DelegatingClass::NewInstance));
}
static void *NewInstance()
{
return new T;
}
};
#define REGISTER_CLASS(class_name) DelegatingClass<class_name> class##class_name(#class_name)
即 REGISTER_CLASS(class_name) 宏定义展开会构造一个模板类实例对象,调用3次宏定义即3个模板类实例对象,调用构造函数
DelegatingClass(const string &name),进而调用Register 完成注册,接下去的流程与以前的程序一样,不再赘述。输出如下:
参考:
C++ primer 第四版 Effective C++ 3rd C++编程规范