美文网首页
单例模式

单例模式

作者: dumphex | 来源:发表于2020-04-18 17:37 被阅读0次

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

1. 介绍

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

考虑两个问题

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

  • 将构造函数设为private, 防止在类外生成栈对象/堆对象
  • 将赋值运算符设为private, 防止赋值对象(上面构造函数为private已经间接确保了不可能赋值).

1.2 外界如何获取单例?

  • 提供public的静态方法getInstance()
  • 保证线程安全

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;

两点说明:

  • 这里使用类的静态变量来实现. 静态对象在main()前被构造执行初始化, 具体可参考C++的全局对象.
  • 但存在一个问题: 如果该类被另一个全局对象/静态对象使用, 但这两个类不在同一源文件(不同的编译单元), 则可能存在问题. 因为不同编译单元的non-local对象的初始化顺序是不确定的.

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;

两点说明

  • 使用智能指针, 保证程序退出前堆对象能正确释放
  • getInstance()需要加锁, 用于保证多线程安全

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较新版本才支持, 推荐使用

相关文章

  • 【设计模式】单例模式

    单例模式 常用单例模式: 懒汉单例模式: 静态内部类单例模式: Android Application 中使用单例模式:

  • Android设计模式总结

    单例模式:饿汉单例模式://饿汉单例模式 懒汉单例模式: Double CheckLock(DCL)实现单例 Bu...

  • 2018-04-08php实战设计模式

    一、单例模式 单例模式是最经典的设计模式之一,到底什么是单例?单例模式适用场景是什么?单例模式如何设计?php中单...

  • 设计模式之单例模式详解

    设计模式之单例模式详解 单例模式写法大全,也许有你不知道的写法 导航 引言 什么是单例? 单例模式作用 单例模式的...

  • Telegram开源项目之单例模式

    NotificationCenter的单例模式 NotificationCenter的单例模式分析 这种单例模式是...

  • 单例模式Java篇

    单例设计模式- 饿汉式 单例设计模式 - 懒汉式 单例设计模式 - 懒汉式 - 多线程并发 单例设计模式 - 懒汉...

  • IOS单例模式的底层原理

    单例介绍 本文源码下载地址 1.什么是单例 说到单例首先要提到单例模式,因为单例模式是单例存在的目的 单例模式是一...

  • 单例

    iOS单例模式iOS之单例模式初探iOS单例详解

  • 单例模式

    单例模式1 单例模式2

  • java的单例模式

    饿汉单例模式 懒汉单例模式

网友评论

      本文标题:单例模式

      本文链接:https://www.haomeiwen.com/subject/ejfwvhtx.html