C++ 设计模式:单例模式(Singleton Pattern)

链接:C++ 设计模式
链接:C++ 设计模式 - 享元模式

单例模式(Singleton Pattern)是创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问这个实例。单例模式在需要全局共享资源或控制实例数量的场景中非常有用,例如数据库连接、日志记录器等。

1.问题分析

在开发中,有些对象需要全局唯一的实例。例如:

  • 配置管理器:应用程序的配置通常需要全局唯一的实例,以确保配置的一致性。
  • 日志记录器:日志记录器需要全局唯一的实例,以便集中管理日志输出。
  • 线程池:线程池需要全局唯一的实例,以便高效地管理线程资源。
  • 数据库连接池:数据库连接池需要全局唯一的实例,以便复用数据库连接,减少连接创建和销毁的开销。

如果这些对象被多次创建,会导致以下问题:

  • 资源浪费:每次创建新实例都会消耗系统资源,导致资源浪费。
  • 状态不一致:多个实例之间的状态可能不一致,导致程序行为不可预测。
  • 管理复杂:多个实例的管理和维护变得复杂,增加了代码的复杂性和维护成本。

为了避免上述问题,我们需要一种机制来确保某个类只有一个实例,并提供一个全局访问点来访问该实例。这就是单例模式的核心需求。

2.实现步骤

  1. 私有化构造函数:将类的构造函数、拷贝构造函数和赋值运算符设为私有,防止外部创建实例。
  2. 定义静态成员变量:用于存储单例对象的唯一实例。
  3. 提供公共静态方法:提供全局访问点来获取单例对象的唯一实例。

3.代码示例

3.1.简单形式

cpp 复制代码
class Singleton {
 public:
  // 删除拷贝构造函数和赋值运算符,防止复制单例对象
  Singleton(const Singleton&) = delete;
  Singleton& operator=(const Singleton&) = delete;

  // 获取单例实例的公共静态方法
  static Singleton& getInstance() {
    // 使用局部静态变量来实现线程安全的单例模式
    static Singleton instance;
    return instance;
  }

  // 示例方法,显示单例实例的地址
  void showMessage() { std::cout << "Singleton instance address: " << this << std::endl; }

 private:
  // 私有构造函数,防止外部创建实例
  Singleton() { std::cout << "Singleton instance created." << std::endl; }

  // 私有析构函数,防止外部删除实例
  ~Singleton() { std::cout << "Singleton instance destroyed." << std::endl; }
};
cpp 复制代码
int main() {
  // 获取单例实例并调用方法
  Singleton& singleton = Singleton::getInstance();
  singleton.showMessage();

  // 尝试获取另一个单例实例
  Singleton& anotherSingleton = Singleton::getInstance();
  anotherSingleton.showMessage();

  return 0;
}

3.2.指针形式

cpp 复制代码
#include <memory>
#include <mutex>
#include <stdexcept>

class Singleton {
 public:
  // 删除拷贝构造函数和赋值运算符,防止复制实例
  Singleton(const Singleton&) = delete;
  Singleton& operator=(const Singleton&) = delete;

  // 获取实例的静态方法
  static Singleton& getInstance() {
    if (!instance) {
      throw std::logic_error("Instance not yet initialized. Call initInstance() first.");
    }
    return *instance;
  }

  // 初始化实例的静态方法
  static void initInstance(int value) {
    std::call_once(initFlag, [&]() { instance.reset(new Singleton(value)); });
  }

  // 示例方法
  void showMessage() { std::cout << "Singleton instance address: " << this << std::endl; }

 private:
  // 私有化构造函数,防止外部创建实例
  Singleton(int value) : value_(value) { std::cout << "Singleton instance created with value: " << value_ << std::endl; }

  // 私有化析构函数,防止外部删除实例
  ~Singleton() { std::cout << "Singleton instance destroyed." << std::endl; }

  // 静态智能指针成员变量,用于保存唯一的实例
  static std::unique_ptr<Singleton> instance;
  // 用于确保单例初始化的标志
  static std::once_flag initFlag;
  // 示例成员变量
  int value_;
};

// 初始化静态成员变量
std::unique_ptr<Singleton> Singleton::instance = nullptr;
std::once_flag Singleton::initFlag;
cpp 复制代码
int main() {
  // 初始化单例实例
  Singleton::initInstance(42);

  // 获取单例实例并调用方法
  Singleton& singleton = Singleton::getInstance();
  singleton.showMessage();

  // 再次获取单例实例并调用方法
  Singleton& singleton2 = Singleton::getInstance();
  singleton2.showMessage();

  return 0;
}
相关推荐
weixin_307779138 小时前
C++代码实现MATLAB中的ode23t函数功能
开发语言·c++·算法·matlab
wuminyu8 小时前
Markword在紧凑对象头上的实现原理剖析
java·linux·c语言·jvm·c++
hansang_IR9 小时前
【代数与组合数学 | 那忘算 5】生成函数 & 例题 & 卷积
c++·算法·多项式·生成函数·母函数
无忧.芙桃9 小时前
数据结构之排序算法(上):从评价指标到插入、希尔、选择与堆排序
c语言·c++·排序算法
syagain_zsx9 小时前
算法基础篇 · 02 高精度(C++ 题解)
开发语言·c++·学习·高精度
6Hzlia9 小时前
【Classic 150 刷题计划】 LeetCode 242. 有效的字母异位词 | C++ 哈希计数与严密防线
c++·算法·leetcode
wabs6669 小时前
关于二叉树【力扣101.对称二叉树的思考】
数据结构·c++·算法·leetcode·二叉树
6Hzlia9 小时前
【Classic 150 刷题计划】 LeetCode 228. 汇总区间 | C++ 双游标区间扫描与 to_string 规范
c++·算法·leetcode
纪念 22910 小时前
C++类和对象(二)
开发语言·c++
钓鱼的肝10 小时前
csp-j-s总结(1)
c++·笔记·算法·青少年编程