设计模式 | 单例模式 | 懒汉&饿汉

什么是单例模式呢?就是只允许有一个实例对象

所以单例模式会有以下特征:

必须是通过静态成员函数去创建那唯一的实例对象,而且这个实例也必须是静态的

还有构造函数必须私有,拷贝构造、赋值重载全部禁用

由单例模式都有哪些场景?

线程池、资源分配、日志记录

数据库连接池: 在多线程环境中,数据库连接的创建和销毁是开销较大的操作,使用单例模式可以确保整个应用程序只有一个数据库连接池实例,避免了资源的浪费。

日志记录器: 在应用程序中,通常只需要一个日志记录器来记录系统的运行状态和错误信息,使用单例模式可以确保所有组件共享同一个日志记录器,避免了多个实例产生的混乱。

配置管理器: 应用程序的配置信息通常是全局共享的,使用单例模式可以确保整个应用程序只有一个配置管理器实例,方便统一管理和修改配置信息。

线程池: 在多线程环境中,线程池可以提高任务处理的效率,使用单例模式可以确保整个应用程序只有一个线程池实例,方便任务的提交和管理。

缓存管理器: 缓存是提高应用程序性能的重要手段之一,使用单例模式可以确保整个应用程序只有一个缓存管理器实例,避免了多个缓存管理器实例之间的数据不一致。

然后又有饿汉模式跟懒汉模式

什么是饿汉模式

在程序启动时即创建单例对象,并且在整个生命周期中保持不变。

在类加载时就创建单例对象,并在程序运行期间一直存在,无论是否需要使用该对象。

线程安全,因为对象在类加载时就已经创建,不会出现多线程竞争的情况。

实现简单,适用于单例对象较小且在应用程序中经常被使用的情况。

cpp 复制代码
#include <iostream>

class Singleton {
public:
    // 获取单例实例的静态方法						#3 获取类的唯一实例对象的接口方法
    static Singleton& getInstance() {
        // 使用静态局部变量保证线程安全的懒汉模式	#2定义唯一的类的实例对象
        static Singleton instance;
        return instance;
    }

    // 将拷贝构造函数删除,防止通过拷贝构造函数创建实例
    Singleton(const Singleton&) = delete;

    // 将赋值操作符删除,防止通过赋值操作符创建实例
    Singleton& operator=(const Singleton&) = delete;

    // 提供一些公共方法
    void doSomething() {
        std::cout << "Singleton is doing something." << std::endl;
    }

private:
    // 将构造函数私有化,防止外部直接创建实例		#1 构造函数私有化
    Singleton() {
        // 可以在构造函数中进行一些初始化操作
    }

    // 将析构函数私有化,防止外部删除实例
    ~Singleton() {
        // 可以在析构函数中进行一些清理工作
    }
};

int main() {

    // 不能通过构造函数自己创建对象,只能通过类的静态方法来获取这个类的唯一对象
    // 通过禁用拷贝构造、赋值重载 都要禁用 
    // 获取单例实例
    Singleton& instance1 = Singleton::getInstance();
    Singleton& instance2 = Singleton::getInstance();
    Singleton& instance3 = Singleton::getInstance();

    // 调用单例实例的方法
    instance1.doSomething();

    return 0;
}

懒汉模式

在需要时才创建单例对象,而不是在程序启动时就创建。

第一次调用 getInstance() 方法时才会创建单例对象,延迟了单例对象的实例化。

线程不安全,如果多个线程同时调用 getInstance() 方法,并且单例对象尚未创建,则可能导致创建多个实例的情况。

需要使用双重检查锁定(Double-Checked Locking)或者使用静态内部类来保证线程安全。

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

//		volate 关键字 当某一个线程给 instace 赋值 其他线程就能立马知道instace 被赋值
//		线程  已经不对 共享变量  instace  缓存
class Singleton{
    public:
        // 是否是可重入函数呢?  		临界区代码段  保证操作的原子性  锁 + 双重判断
        static Singleton* getInstance(){
            
            if(instance == nullptr){			// 1重

                std::lock_guard<std::mutex> lock(mutex_);

                if(instance == nullptr){		// 2重
                    
                    instance = new Singleton();
                }
                
            }
            return instance;
        }
    private:
        static Singleton* volate instance;		// #2 定义一个唯一的类的实例对象
        // #1 构造函数私有化
        Singleton(){}
        Singleton(const Singleton&) = delete;
        Singleton& operator = (const Singleton&) = delete;
        // 静态成员变量用于保证线程安全
        static std::mutex mutex_;
};
Singleton*volate  Singleton::instance = nullptr;
std::mutex Singleton::mutex_;

int main(){
    Singleton* p1 = Singleton::getInstance();		// instance 为nullptr 创建 实例对象
    Singleton* p2 = Singleton::getInstance();		// instance 不为空  直接返回 实例
}
相关推荐
程序员JerrySUN20 分钟前
设计模式每日硬核训练 Day 14:组合模式(Composite Pattern)完整讲解与实战应用
设计模式·组合模式
碎梦归途26 分钟前
23种设计模式-创建型模式之工厂方法模式(Java版本)
java·设计模式·工厂方法模式
XU磊2601 小时前
Java 工厂设计模式详解:用统一入口打造灵活可扩展的登录系统----掌握 Spring 源码的基础第一步
java·设计模式
匹马夕阳2 小时前
java开发中的设计模式之工厂模式
java·设计模式
Pasregret2 小时前
设计模式入门:从 GoF 分类到 SOLID 原则实战
java·设计模式
Light604 小时前
Python依赖注入完全指南:高效解耦、技术深析与实践落地
python·设计模式·单元测试·fastapi·依赖注入·解耦
都叫我大帅哥5 小时前
代码界的「俄罗斯套娃」:组合模式的嵌套艺术
java·后端·设计模式
渊渟岳8 小时前
为了掌握设计模式,开发了一款Markdown 文本编辑器软件(已开源)
java·设计模式
邪恶的贝利亚12 小时前
设计模式实践:模板方法、观察者与策略模式详解
设计模式·策略模式
匹马夕阳16 小时前
Java开发中的设计模式之观察者模式详细讲解
java·观察者模式·设计模式