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;
}

优缺点

说明
✅ 优点 节约资源,避免重复创建
✅ 优点 全局共享资源,防止冲突
✅ 优点 控制访问,全局只有一个入口
❌ 缺点 没有接口,没有继承,很难扩展新功能
❌ 缺点 单元测试困难(全局状态难以隔离)
❌ 缺点 生命周期管理不灵活,一旦创建,无法手动销毁、重启
❌ 缺点 到处都能直接调用,代码可读性变差,难以清理依赖
相关推荐
读书札记20222 小时前
1.单例模式
单例模式
妙蛙种子3111 天前
【Java设计模式 | 创建者模式】单例模式
java·开发语言·后端·单例模式·设计模式
Momentary_SixthSense2 天前
单例模式全解析:5种写法 + 破坏与防护
单例模式
程序员榴莲2 天前
设计模式之GoF设计模式(单例模式
单例模式·设计模式
大数据新鸟4 天前
单例模式的变种
单例模式
yaaakaaang4 天前
一、单例模式
单例模式
Yupureki4 天前
《Linux系统编程》20.常见程序设计模式
linux·服务器·c语言·c++·单例模式·建造者模式·责任链模式
pedestrian_h5 天前
Java单例模式回顾
java·单例模式·设计模式
苏渡苇5 天前
枚举的高级用法——用枚举实现策略模式和状态机
java·单例模式·策略模式·枚举·状态机·enum
·心猿意码·7 天前
C++ 线程安全单例模式的底层源码级解析
c++·单例模式