软件设计模式之单例模式

发布于:2025-09-06 ⋅ 阅读:(17) ⋅ 点赞:(0)

软件设计模式之单例模式

什么是单例模式

单例设计模式(Singleton Pattern)是一种创建型设计模式,旨在确保一个类只有一个实例,并提供一个全局访问点来访问该实例。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。
简而言之,就是全局只有一个对象实例

实现方式

单例模式的实现方式有多种,以下是几种常见的实现方式:

饿汉式

饿汉式在类加载时就创建实例,因此线程安全,但可能会浪费内存。

//饿汉模式
//核心思想:在类加载时立即初始化单例对象
class SingLeton
{
    public:
    static SingLeton& getInstance()
    {
        return _eton;
    }

    int getData()
    {
        return _data;
    }

    protected:


    private:
    int _data;
    private:
    static SingLeton _eton;
    SingLeton()
    :_data(666) 
    {
        std::cout << "单例对象构造" << std::endl;
    };
    ~SingLeton() {};
    SingLeton(const SingLeton& eton) = delete;
};

SingLeton SingLeton::_eton;

懒汉式

懒汉式在第一次使用时才创建实例,节省资源,但需要加锁以确保线程安全。

//懒汉模式
//核心思想:延迟初始化,仅在首次请求时创建实例
class SingLeton
{
    public:
    static SingLeton& getInstance()
    {
        static SingLeton _eton;
        return _eton;
    }

    int getData()
    {
        return _data;
    }

    protected:


    private:
    int _data;
    private:
    SingLeton()
    :_data(666) 
    {
        std::cout << "单例对象构造" << std::endl;
    };
    ~SingLeton() {};
    SingLeton(const SingLeton& eton) = delete;
};

双重检查锁

双重检查锁在多线程环境下性能较好,但实现较复杂。

#include <mutex>
#include <atomic>

class Singleton {
private:
    static std::atomic<Singleton*> instance;
    static std::mutex mtx;

    Singleton() = default;
    ~Singleton() = default;
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

public:
    static Singleton* getInstance() {
        Singleton* tmp = instance.load(std::memory_order_acquire);
        if (tmp == nullptr) {
            std::lock_guard<std::mutex> lock(mtx);
            tmp = instance.load(std::memory_order_relaxed);
            if (tmp == nullptr) {
                tmp = new Singleton();
                instance.store(tmp, std::memory_order_release);
            }
        }
        return tmp;
    }
};

// 静态成员初始化
std::atomic<Singleton*> Singleton::instance{nullptr};
std::mutex Singleton::mtx;
 

静态内部类

静态内部类方式既能确保线程安全,又能实现延迟加载

// Meyer's Singleton (C++11起线程安全)
class Singleton {
public:
    static Singleton& getInstance() {
        static Singleton instance;
        return instance;
    }
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
private:
    Singleton() = default;
    ~Singleton() = default;
};
 

枚举

class Singleton {
public:
    enum { INSTANCE };
    
    static Singleton& getInstance() {
        static Singleton instance;
        return instance;
    }
    
    void showMessage() {
        std::cout << "Singleton instance created" << std::endl;
    }
    
private:
    Singleton() {}
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
};

int main() {
    Singleton::getInstance().showMessage();
    return 0;
}
 

优缺点

优点

  1. 资源管理:单例模式能高效管理共享资源,确保程序内仅存在单一对象实例,从而降低资源消耗和内存占用。

  2. 全局访问:该模式提供了全局访问唯一对象的便捷途径,使得程序各模块都能轻松获取和使用该实例。

  3. 线程安全:在多线程环境中,单例模式确保仅有一个线程能创建实例,有效防止竞态条件和数据不一致问题。

  4. 创建控制:通过集中管理对象创建过程,单例模式避免了程序多处随意实例化对象的情况,提升了代码的可维护性和控制性。

缺点

  1. 灵活性不足:单例模式严格限制对象实例化,在特定场景下会降低系统灵活性。若后续开发需要支持多实例,往往需要进行较大规模的代码调整。

  2. 高耦合问题:该模式将对象创建与使用紧密绑定,容易导致其他模块过度依赖单例对象,从而影响系统的可维护性和扩展性。

  3. 测试复杂度高:单元测试时,单例对象需要特殊的环境模拟,这种额外的测试准备增加了测试工作的难度。

  4. 全局状态风险:作为全局访问点,单例对象在多线程或分布式环境中可能引发并发问题,必须谨慎处理线程安全和锁机制。

  5. 扩展性受限:当需要增强或修改单例功能时,往往涉及模式重构,这不仅提高了系统复杂度,也增加了维护难度。

使用场景

单例模式适用于以下场景:

  1. 唯一序列号生成需求
  2. Web 应用计数器实现
  3. 数据库连接管理:采用单例模式实现数据库连接管理器,确保应用全局共享单一连接实例,有效减少连接创建和释放的资源消耗
  4. 配置统一管理:通过单例对象封装应用配置信息,保证系统配置一致性,消除配置冲突风险
  5. 稀缺资源管控:对文件句柄、网络连接等有限资源,运用单例模式实现统一调度与分配
  6. 集中日志管理:基于单例模式构建全局日志记录器,为系统各模块提供统一日志接口,便于日志的集中维护
  7. 应用主控入口:采用单例模式实现应用主入口,确保启动和初始化流程仅执行一次,提供标准化的程序入口

网站公告

今日签到

点亮在社区的每一天
去签到