C++实现设计模式---单例模式 (Singleton)

单例模式 (Singleton)

概念

单例模式 确保一个类在整个程序生命周期中只有一个实例,并提供一个全局访问点。

它是一种创建型设计模式,广泛用于需要共享资源的场景。


使用场景

  1. 配置管理器:程序中需要一个全局的配置对象。
  2. 日志系统:确保日志记录器只有一个实例。
  3. 数据库连接池:共享一个数据库连接实例。

实现单例模式的要点

  1. 私有构造函数 :防止外部通过 new 操作符创建实例。
  2. 静态成员变量:保存类的唯一实例。
  3. 静态方法:提供全局访问点。
  4. 线程安全:确保多线程环境下实例只有一个。

示例代码:线程安全的单例模式

cpp 复制代码
#include <iostream>
#include <mutex>

// 单例类定义
class Singleton {
private:
    // 静态实例指针,用于保存唯一实例
    static Singleton* instance;

    // 互斥锁,保证多线程环境下的线程安全
    static std::mutex mtx;

    // 私有构造函数,禁止外部实例化
    Singleton() {
        std::cout << "Singleton Created!" << std::endl;
    }

public:
    // 禁止拷贝构造和赋值操作
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

    // 静态方法,用于获取唯一实例
    static Singleton* getInstance() {
        // 双重检查锁定,减少锁的开销
        if (instance == nullptr) {
            std::lock_guard<std::mutex> lock(mtx); // 加锁
            if (instance == nullptr) {
                instance = new Singleton(); // 创建唯一实例
            }
        }
        return instance;
    }

    // 提供一些功能方法
    void doSomething() {
        std::cout << "Singleton is working!" << std::endl;
    }

    // 销毁实例(可选)
    static void destroyInstance() {
        delete instance;
        instance = nullptr;
    }
};

// 静态成员变量初始化
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mtx;

// 主函数:测试单例模式
int main() {
    // 获取单例实例
    Singleton* s1 = Singleton::getInstance();
    Singleton* s2 = Singleton::getInstance();

    // 调用单例方法
    s1->doSomething();

    // 检查两个实例是否相同
    std::cout << "Are s1 and s2 the same? " << (s1 == s2 ? "Yes" : "No") << std::endl;

    // 销毁单例实例
    Singleton::destroyInstance();

    return 0;
}

代码详解

1. 私有化构造函数

  • 目的:禁止通过 new 操作符创建实例。
cpp 复制代码
Singleton() {
    std::cout << "Singleton Created!" << std::endl;
}

2. 静态成员变量

  • 保存唯一的单例实例,初始值为 nullptr
cpp 复制代码
static Singleton* instance;

3. 互斥锁

  • 确保在多线程环境下,多个线程不会同时创建实例。
cpp 复制代码
static std::mutex mtx;

4. 静态方法 getInstance

  • 提供唯一实例的全局访问点。
  • 双重检查锁定:减少锁的开销,提高性能。
cpp 复制代码
static Singleton* getInstance() {
    if (instance == nullptr) {
        std::lock_guard<std::mutex> lock(mtx);
        if (instance == nullptr) {
            instance = new Singleton();
        }
    }
    return instance;
}

5. 销毁实例

  • 可选:在程序结束时清理单例实例。
cpp 复制代码
static void destroyInstance() {
    delete instance;
    instance = nullptr;
}

运行结果

执行代码输出

复制代码
Singleton Created!
Singleton is working!
Are s1 and s2 the same? Yes

单例模式的优缺点

优点

  1. 全局唯一实例:确保实例唯一性。
  2. 延迟初始化:实例在第一次使用时才会创建。
  3. 线程安全:双重检查锁定保证线程安全。

缺点

  1. 难以测试:单例模式引入全局状态,可能影响单元测试。
  2. 不适合频繁访问的场景:线程安全的实现有一定性能开销。
  3. 内存泄漏风险:如果程序结束时未释放实例,可能造成内存泄漏。

适合扩展的改进

  1. 懒汉式与饿汉式:可选择延迟初始化(懒汉式)或直接初始化(饿汉式)。
  2. 智能指针管理 :用 std::unique_ptr 管理单例实例,避免内存泄漏。
  3. 多线程优化 :采用 C++11 的 std::call_once 确保线程安全。
相关推荐
aaaweiaaaaaa5 小时前
c++基础学习(学习蓝桥杯 ros2有C基础可看)
c++·学习·蓝桥杯·lambda·ros2·智能指针·c++类
一拳一个呆瓜5 小时前
【MFC】对话框属性:字体 (Font Name) 和 大小 (Font Size)
c++·mfc
RickyWasYoung6 小时前
【代码】matlab-遗传算法工具箱
开发语言·matlab
郝学胜-神的一滴6 小时前
基于OpenGL封装摄像机类:视图矩阵与透视矩阵的实现
c++·qt·线性代数·矩阵·游戏引擎·图形渲染
啊?啊?6 小时前
14 C++ STL 容器实战:stack/list 模拟实现指南 + priority_queue 用法及避坑技巧
c++·
汉克老师6 小时前
第十四届蓝桥杯青少组C++选拔赛[2023.2.12]第二部分编程题(4、最大空白区)
c++·算法·蓝桥杯·蓝桥杯c++·c++蓝桥杯
土了个豆子的7 小时前
03.缓存池
开发语言·前端·缓存·visualstudio·c#
羚羊角uou7 小时前
【Linux】匿名管道和进程池
linux·c++·算法
_extraordinary_7 小时前
Java 多线程(一)
java·开发语言
曙曙学编程7 小时前
stm32——独立看门狗,RTC
c语言·c++·stm32·单片机·嵌入式硬件