单例模式

2020-07-12  本文已影响0人  小跑001

有2个星期没过来了, 这2个星期忙着考试.
言归正传, 今天想写下单例模式, 有时候想写一个完善的单例模式还是需要考虑一些东西的.

1 先看下普通的单例模式:

class TestSingle {

 private:
     TestSingle();
     TestSingle(const TestSingle&);
     TestSingle &operator = (const TestSingle&);

 public:
    static TestSingle* GetInstance() {
            static TestSingle s;
            return &s;
     }
};

2 多线程单例

还有一种变种, 有时候希望在单例初始化里面调用一些初始化的功能就要考虑多线程安全的问题了. 还是直接看代码

#include <mutex>
#include <atomic>

class TestSingle {

 private:
     TestSingle();
     TestSingle(const TestSingle&);
     TestSingle &operator = (const TestSingle&);
     void Init();

 public:
     static TestSingle* GetInstance() {
         if (single_) {
             return single_;
         }

         std::lock_guard<std::mutex> lck (single_mtx_);
         if (single_) {  // 注意这里需要再次判断, 避免再次初始化
             return single_;
         }
         TestSingle* tmp = new(TestSingle); // 不要直接赋值给single_, 以防别的线程获取到没有初始化的指针
         tmp->Init();
         single_ = tmp;
         return single_;
     }

 private:
     static std::atomic<TestSingle*> single_; // static. 通过atomic达到内存屏障, 避免指令优化, 导致获取未初始化的变量. 
     static std::mutex single_mtx_; // static
};

3 单例模版

然而单例多了, 每次都这么写一遍就浪费时间了, 能不能抽象出来, 形成一个模版呢, 还是看代码吧.

template < typename T >
class Singleton {
  public:
    static T* GetInstance() {
      static T instance;
      return &instance;
    }

    Singleton(const Singleton&) = delete;
    Singleton& operator= (const Singleton) = delete;

  protected: // 注意这里的访问权限, 允许子类可以访问, 否则无法创建对象
    Singleton() { };
    virtual ~Singleton() {std::cout << "deconstructor Singleton" << std::endl; }
};

class Test: public Singleton<Test> {
    friend class Singleton<Test>; // 方便访问这里的私有构造函数以及析构函数.
 private:
    Test(){}
    ~Test(){std::cout << "deconstructor Test" << std::endl; }
};

int main() {
    Test* t = Test::GetInstance();
    return 0;
}


上一篇 下一篇

猜你喜欢

热点阅读