跳转到内容

C++ 单例模式

来自代码酷

C++单例模式[编辑 | 编辑源代码]

单例模式(Singleton Pattern)是软件工程中一种常用的设计模式,属于创建型模式的一种。它确保一个类只有一个实例,并提供一个全局访问点。单例模式通常用于管理共享资源,如配置管理、日志记录或数据库连接等。

介绍[编辑 | 编辑源代码]

单例模式的核心思想是限制类的实例化次数,确保在整个程序运行期间仅存在一个实例。这在以下场景中非常有用:

  • 需要控制资源访问(如文件系统或数据库连接)。
  • 需要全局状态管理(如应用程序配置)。
  • 需要共享数据或服务(如缓存管理器)。

单例模式的特点[编辑 | 编辑源代码]

  • 私有构造函数:防止外部直接实例化。
  • 静态成员变量:存储唯一实例。
  • 静态访问方法:提供全局访问点(如 `getInstance()`)。
  • 线程安全(可选):确保多线程环境下仅创建一个实例。

实现方式[编辑 | 编辑源代码]

基础实现(非线程安全)[编辑 | 编辑源代码]

以下是一个最简单的单例模式实现,但仅适用于单线程环境:

class Singleton {
private:
    static Singleton* instance;  // 静态成员变量,存储唯一实例
    Singleton() {}              // 私有构造函数

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

    // 静态方法,提供全局访问点
    static Singleton* getInstance() {
        if (instance == nullptr) {
            instance = new Singleton();
        }
        return instance;
    }

    void doSomething() {
        std::cout << "Singleton is doing something." << std::endl;
    }
};

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

使用示例:

int main() {
    Singleton* singleton = Singleton::getInstance();
    singleton->doSomething();
    return 0;
}

输出:

Singleton is doing something.

线程安全实现(C++11及以上)[编辑 | 编辑源代码]

在多线程环境中,上述实现可能导致多个实例被创建。以下是线程安全的实现方式:

#include <mutex>

class ThreadSafeSingleton {
private:
    static ThreadSafeSingleton* instance;
    static std::mutex mtx;       // 互斥锁,确保线程安全
    ThreadSafeSingleton() {}     // 私有构造函数

public:
    ThreadSafeSingleton(const ThreadSafeSingleton&) = delete;
    ThreadSafeSingleton& operator=(const ThreadSafeSingleton&) = delete;

    static ThreadSafeSingleton* getInstance() {
        std::lock_guard<std::mutex> lock(mtx);  // 加锁
        if (instance == nullptr) {
            instance = new ThreadSafeSingleton();
        }
        return instance;
    }
};

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

更高效的线程安全实现(Meyer's Singleton)[编辑 | 编辑源代码]

C++11 引入了静态局部变量的线程安全特性,可以利用这一点简化实现:

class MeyersSingleton {
private:
    MeyersSingleton() {}  // 私有构造函数

public:
    MeyersSingleton(const MeyersSingleton&) = delete;
    MeyersSingleton& operator=(const MeyersSingleton&) = delete;

    static MeyersSingleton& getInstance() {
        static MeyersSingleton instance;  // 线程安全,C++11保证
        return instance;
    }
};

实际应用案例[编辑 | 编辑源代码]

日志管理器[编辑 | 编辑源代码]

单例模式常用于日志系统,确保所有日志消息通过同一个实例写入文件:

class Logger {
private:
    static Logger* instance;
    std::ofstream logFile;

    Logger() {
        logFile.open("app.log", std::ios::app);
    }

public:
    static Logger* getInstance() {
        if (instance == nullptr) {
            instance = new Logger();
        }
        return instance;
    }

    void log(const std::string& message) {
        logFile << message << std::endl;
    }

    ~Logger() {
        logFile.close();
    }
};

Logger* Logger::instance = nullptr;

使用示例:

int main() {
    Logger::getInstance()->log("Application started");
    Logger::getInstance()->log("Performing task...");
    return 0;
}

配置管理器[编辑 | 编辑源代码]

单例模式也适用于全局配置管理:

#include <unordered_map>

class ConfigManager {
private:
    static ConfigManager* instance;
    std::unordered_map<std::string, std::string> config;

    ConfigManager() {
        // 加载默认配置
        config["theme"] = "dark";
        config["language"] = "en";
    }

public:
    static ConfigManager* getInstance() {
        if (instance == nullptr) {
            instance = new ConfigManager();
        }
        return instance;
    }

    std::string getConfig(const std::string& key) {
        return config[key];
    }

    void setConfig(const std::string& key, const std::string& value) {
        config[key] = value;
    }
};

ConfigManager* ConfigManager::instance = nullptr;

单例模式的优缺点[编辑 | 编辑源代码]

优点[编辑 | 编辑源代码]

  • 提供对唯一实例的受控访问。
  • 避免全局变量污染命名空间。
  • 支持延迟初始化(Lazy Initialization)。

缺点[编辑 | 编辑源代码]

  • 违反单一职责原则(管理自身生命周期)。
  • 可能导致代码耦合度高。
  • 难以进行单元测试(由于全局状态)。
  • 多线程环境下需要额外处理。

类图[编辑 | 编辑源代码]

以下是单例模式的类图表示:

classDiagram class Singleton { -static Singleton* instance -Singleton() +static Singleton* getInstance() +doSomething() }

数学表示[编辑 | 编辑源代码]

单例模式可以形式化表示为:

Let S be a class with:{1. !sS (unique instance)2. xS,x=s (all references point to s)3. Constructor C:S is private

总结[编辑 | 编辑源代码]

单例模式是C++中一种重要的设计模式,用于确保类只有一个实例并提供全局访问点。虽然实现简单,但在多线程环境中需要特别注意线程安全问题。现代C++(C++11及以上)提供了更简洁的线程安全实现方式。开发者应谨慎使用单例模式,避免过度使用导致代码难以维护。

对于初学者,建议从基础的单线程实现开始理解概念,再逐步学习线程安全版本。高级开发者可以考虑依赖注入等替代方案,以改善代码的可测试性和模块化程度。