现在的位置: 首页 > 综合 > 正文

Singleton模式的几种实现方式

2013年06月29日 ⁄ 综合 ⁄ 共 2999字 ⁄ 字号 评论关闭

//下面大概是设计模式书中讲到的实现
class Singleton
{
public:
 static Singleton* Instance(void)
 {
  if(NULL==instance_)
  {
   instance_ = new Singleton;
  }
  return instance_;
 }
private:
 Singleton(void){}
 ~Singleton(void){}
private:
 static Singleton* instance_;
};

Singleton* Singleton::instance_ = NULL;

//但这个实现有几个问题
//1.instance_究竟什么时间销毁? 为类提供一个静态方法DestroyInstance?
// 那在程序退出时究竟什么时间调用之合适呢?既要保证资源得到释放,
// 又要保证在资源释放后没有其它代码引用它了。
//2.在多线程的环境下,有可能会new出两个实例
//

//对于上面的两个问题,有现在的解决方案
class Singleton
{
public:
 static Singleton& Instance(void)
 {
  static Singleton instance;
  return instance;
 }
private:
 Singleton(void){}
 ~Singleton(void){}
};

//但用户如果需要控制Instance的生命期呢?但同时要保证程序在退出时正确释放
//资源,又同时保证多线程安全呢?可以按下面的方式进行实现:

class Singleton
{
private:
 class CriticalSection
 {
 public:
  CriticalSection(void)
  {
   InitializeCriticalSection(&cs);
  }
  ~CriticalSection(void)
  {
   DeleteCriticalSection(&cs);
  }
  void Lock(void)
  {
   EnterCriticalSection(&cs);
  }
  void Unlock(void)
  {
   LeaveCriticalSection(&cs);
  }
 private:
  CRITICAL_SECTION cs;
 };
 class Lock
 {
 public:
  Lock(CriticalSection* pcs) : pcs_(pcs)
  {
   assert(NULL!=pcs_);
   pcs_->Lock();
  }
  ~Lock(void)
  {
   pcs_->Unlock();
  }
 private:
  CriticalSection* pcs_;
 }

public:
 //返回引用是为了避免调用者不小心delete掉了。
 static Singleton& Instance(void)
 {
  //这就是著名的双检测锁定,既保证了同步,又保证同步的开销最小
  if(NULL==instance_.get())
  {
   Lock lock(&cs_);
   if(NULL==instance_.get())
   {
    instance_.reset(new Singleton);
   }   
  }
  return *instance_.get();
 }
 static void DestroyInstance(void)
 {
  Lock lock(&cs_);
  instance_.reset();
 }
private:
 Singleton(void){}
 //不能将~Singleton声明为private,因为auto_ptr需要
private:
 static auto_ptr<Singleton> instance_; //auto_ptr保证资源最后一定能得到释放
 static CriticalSection cs_;
};

auto_ptr<Singleton> Singleton::instance_;
Singleton::CriticalSection Singleton::cs_;

//为了进一步方便使用, 可以将Singleton声明为模板类

template<class T>
class SingletonT
{
private:
 class CriticalSection
 {
 public:
  CriticalSection(void)
  {
   InitializeCriticalSection(&cs);
  }
  ~CriticalSection(void)
  {
   DeleteCriticalSection(&cs);
  }
  void Lock(void)
  {
   EnterCriticalSection(&cs);
  }
  void Unlock(void)
  {
   LeaveCriticalSection(&cs);
  }
 private:
  CRITICAL_SECTION cs;
 };
 class Lock
 {
 public:
  Lock(CriticalSection* pcs) : pcs_(pcs)
  {
   assert(NULL!=pcs_);
   pcs_->Lock();
  }
  ~Lock(void)
  {
   pcs_->Unlock();
  }
 private:
  CriticalSection* pcs_;
 }

public:
 //返回引用是为了避免调用者不小心delete掉了。
 static T& Instance(void)
 {
  //这就是著名的双检测锁定,既保证了同步,又保证同步的开销最小
  //有人说双检测锁定并不可靠,其实那是JAVA程序员的担心,C++及CRITICAL_SECTION
  //在此是可以保证的, 可以放心使用的
  if(NULL==instance_.get())
  {
   Lock lock(&cs_);
   if(NULL==instance_.get())
   {
    instance_.reset(new T);
   }   
  }
  return *instance_.get();
 }
 static void DestroyInstance(void)
 {
  Lock lock(&cs_);
  instance_.reset();
 }
protected:
 SingletonT(void){}
 //不能将~Singleton声明为private,因为auto_ptr需要
private:
 static auto_ptr<T> instance_; //auto_ptr保证资源最后一定能得到释放
 static CriticalSection cs_;
};

class TestClass : public SingletonT<TestClass>
{
public:
 void Run()
 {
 }
};

int main(int argc, const char **argv)
{
 argc;
 argv;
 TestClass::Instance().Run();
 TestClass::DestroyInstance();//销毁这一个唯一的实例
 TestClass::Instance().Run();//它又起死回生了
 return 0;
}

抱歉!评论已关闭.