单例模式

2020-04-18  本文已影响0人  dumphex

程序员自我修养(ID: dumphex)

1. 介绍

单例模式, 是23种GOF设计模式之一, 属于创建型. 顾名思义, 单例模式就是一个类只能实例化出一个对象.

考虑两个问题

1.1 如何保证只能实例出一个对象?

1.2 外界如何获取单例?

2. 实现方法

2.1 饿汉式

饿汉式, 就是不管是否用到, 默认都会创建.

// SingletonEager
class SingletonEager {
 public:
  static SingletonEager & getInstance() {
    return m_instance;
  }

 private:
  static SingletonEager m_instance;

  SingletonEager() {
    std::cout << __FUNCTION__ << " is caled. " << std::endl;
  }

  ~SingletonEager() {
    std::cout << __FUNCTION__ << " is caled. " << std::endl;
  }

  SingletonEager(const SingletonEager & s);
  SingletonEager& operator =(const SingletonEager & s);
};

SingletonEager SingletonEager::m_instance;

两点说明:

2.2 懒汉式

懒汉式, 就是第一次调用到的时候才去创建.

// SingletonLazy
class SingletonLazy {
 public:
  static std::unique_ptr<SingletonLazy> & getInstance() {
    std::lock_guard<std::mutex> lck(m_mtx);
    if(m_instance == nullptr) {
      m_instance.reset(new SingletonLazy());
    }

    return m_instance;
  }

  ~SingletonLazy() {
    std::cout << __FUNCTION__ << " is caled. " << std::endl;
  }

 private:
  static std::mutex m_mtx;
  static std::unique_ptr<SingletonLazy> m_instance;

  SingletonLazy() {
    std::cout << __FUNCTION__ << " is caled. " << std::endl;
  }

  SingletonLazy(const SingletonLazy & s);
  SingletonLazy& operator =(const SingletonLazy & s);
};

std::mutex SingletonLazy::m_mtx;
std::unique_ptr<SingletonLazy> SingletonLazy::m_instance;

两点说明

2.3 局部静态对象

Effective C++一书中item4(确保对象初始化)中, 提到了Scott Meyer版本的实现

// local static
class SingletonLocalStatic {
 public:
  static SingletonLocalStatic & getInstance() {
    static SingletonLocalStatic instance;
    return instance;
  }

 private:
  SingletonLocalStatic() {
     std::cout << __FUNCTION__ << " is caled. " << std::endl;
  }

  ~SingletonLocalStatic() {
     std::cout << __FUNCTION__ << " is caled. " << std::endl;
  }

  SingletonLocalStatic(const SingletonLocalStatic & s);
  SingletonLocalStatic& operator =(const SingletonLocalStatic & s);
};

C++11/较新的gcc编译器, 能保证局部静态对象的线程安全, 具体实现原理可参考之前研究过的C++的局部静态对象

3. 总结

实现方式 说明
饿汉式 若被其它编译单元的全局对象/静态对象使用, 有可能存在初始化顺序问题
懒汉式 加锁影响性能
局部静态对象 C++11/gcc较新版本才支持, 推荐使用
上一篇 下一篇

猜你喜欢

热点阅读