23种设计模式 - 单例模式(Singleton)

单例模式(Singleton)------ 全局就我一个,多了没有,爱用不用

大白话解释

想象一个公司只有一台打印机。不管谁来打印,用的都是同一台机器。如果每次有人要打印就新买一台,那公司得破产。

单例模式就是:整个程序运行期间,某个类只能有一个实例,所有人都共用这一个。

常见场景:

  • 配置文件管理器(配置只需加载一次)
  • 日志系统(全局写同一个日志)
  • 数据库连接池(连接资源宝贵)
  • 窗口管理器(只有一个主窗口)

核心思路

  1. 把构造函数藏起来 (设为 private),外面没法 new 出来
  2. 自己内部保存唯一实例
  3. 提供一个全局访问点(静态方法)

C++ 代码示例

版本一:懒汉式(用到的时候才创建)

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

class ConfigManager {
private:
    // 私有构造函数,外部无法直接 new
    ConfigManager() {
        std::cout << "配置管理器初始化完成!\n";
        dbHost = "localhost";
        dbPort = 3306;
    }

    // 禁止拷贝和赋值(C++11 写法)
    ConfigManager(const ConfigManager &) = delete;
    ConfigManager &operator=(const ConfigManager &) = delete;

    std::string dbHost;
    int dbPort;

public:
    // 全局访问点:第一次调用时创建实例
    static ConfigManager &instance() {
        static ConfigManager instance; // C++11 保证线程安全
        return instance;
    }

    std::string getDbHost() const { return dbHost; }
    int getDbPort() const { return dbPort; }

    void setDbHost(const std::string& host) { dbHost = host; }
};

int main() {
    // 获取单例
    ConfigManager &config1 = ConfigManager::instance();
    ConfigManager &config2 = ConfigManager::instance();

    // 验证是同一个对象
    std::cout << "是同一个对象吗?" << (&config1 == &config2 ? "是" : "否") << "\n";

    // 通过 config1 修改
    config1.setDbHost("192.168.0.100");

    // config2 也能看到修改(因为本来就是同一个)
    std::cout << "config2 的数据库地址:" << config2.getDbHost() << "\n";

    return 0;
}

输出:

复制代码
配置管理器初始化完成!
是同一个对象吗?是
config2 的数据库地址:192.168.0.100

版本二:线程安全的指针版(多线程环境)

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

class Logger {
private:
    static Logger *instance;
    static std::mutex mtx;

    Logger() {
        std::cout << "日志系统启动\n";
    }

public:
    static Logger *instance() {
        if (instance == nullptr) {           // 第一次检查(提高效率)
            std::lock_guard<std::mutex> lock(mtx);
            if (instance == nullptr) {       // 第二次检查(保证线程安全)
                instance = new Logger();
            }
        }
        return instance;
    }

    void log(const std::string &msg) {
        std::cout << "[LOG] " << msg << "\n";
    }
};

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

int main() {
    Logger::instance()->log("程序启动");
    Logger::instance()->log("用户登录成功");
    return 0;
}

优缺点

说明
✅ 优点 节约资源,避免重复创建
✅ 优点 全局共享资源,防止冲突
✅ 优点 控制访问,全局只有一个入口
❌ 缺点 没有接口,没有继承,很难扩展新功能
❌ 缺点 单元测试困难(全局状态难以隔离)
❌ 缺点 生命周期管理不灵活,一旦创建,无法手动销毁、重启
❌ 缺点 到处都能直接调用,代码可读性变差,难以清理依赖
相关推荐
摇滚侠2 天前
Java 饿汉式 单例模式
java·开发语言·单例模式
游乐码3 天前
Unity坦克案例疑难记录(一)
unity·单例模式
想学会c++5 天前
单例模式笔记总结
c++·笔记·单例模式
是个西兰花6 天前
单列模式和C++中的类型转换
c++·单例模式·设计模式·rtti
nnsix6 天前
设计模式 - 单例模式 笔记
笔记·单例模式·设计模式
cui_ruicheng6 天前
Linux线程(四):线程池、日志系统与单例模式
linux·开发语言·单例模式
2301_815279527 天前
实战分享实现 C++ 管理类单例模式:特点与最佳实践
javascript·c++·单例模式
阿维的博客日记7 天前
细说DCL单例模式和volatile有什么关系,volatile在DCL中是必要的吗??
单例模式·synchronized·happens-before
c++之路7 天前
单例模式(Singleton Pattern)
开发语言·c++·单例模式
青山师8 天前
CompletableFuture深度解析:异步编程范式与源码实现
java·单例模式·面试·性能优化·并发编程