单例模式的3种实现方式:

  • 饿汉式、
  • 懒汉式
  • 双重检查

1. 饿汉式(Eager Initialization)

饿汉式单例模式在类加载时就创建实例,因此线程安全,但可能会增加程序启动时间和内存消耗。

#include <iostream>

class Singleton {
public:
    // 获取单例对象的静态方法
    static Singleton& getInstance() {
        static Singleton instance;
        return instance;
    }

    // 删除拷贝构造函数和赋值运算符重载,确保只能通过 getInstance 获取单例
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

private:
    // 私有构造函数,防止外部实例化
    Singleton() {}
};

int main() {
    Singleton& s1 = Singleton::getInstance();
    Singleton& s2 = Singleton::getInstance();

    // s1 和 s2 是同一个实例
    std::cout << (&s1 == &s2) << std::endl; // 输出 1

    return 0;
}

在这个示例中,静态局部变量 instance 在程序启动时就会初始化,因此可以保证线程安全性,但可能会增加程序启动时间和内存消耗。

 

2. 懒汉式(Lazy Initialization)

懒汉式单例模式在第一次使用时才会创建实例,避免了启动时间和内存消耗,但需要考虑线程安全问题。

#include <iostream>
#include <mutex>

class Singleton {
public:
    // 获取单例对象的静态方法
    static Singleton& getInstance() {
        std::lock_guard<std::mutex> lock(mutex);
        if (!instance)
            instance = new Singleton();
        return *instance;
    }

    // 删除拷贝构造函数和赋值运算符重载,确保只能通过 getInstance 获取单例
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

private:
    // 私有构造函数,防止外部实例化
    Singleton() {}

    // 静态成员变量和互斥量
    static Singleton* instance;
    static std::mutex mutex;
};

// 静态成员变量的定义
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mutex;

int main() {
    Singleton& s1 = Singleton::getInstance();
    Singleton& s2 = Singleton::getInstance();

    // s1 和 s2 是同一个实例
    std::cout << (&s1 == &s2) << std::endl; // 输出 1

    return 0;
}

在这个示例中,getInstance() 方法会在第一次调用时创建实例,使用了双重检查锁定的方式来确保线程安全性。

 

3. 双重检查锁定(Double-Checked Locking)

双重检查锁定是对懒汉式的改进,避免了每次调用都需要加锁的性能损耗。

#include <iostream>
#include <mutex>

class Singleton {
public:
    // 获取单例对象的静态方法
    static Singleton& getInstance() {
        if (!instance) {
            std::lock_guard<std::mutex> lock(mutex);
            if (!instance)
                instance = new Singleton();
        }
        return *instance;
    }

    // 删除拷贝构造函数和赋值运算符重载,确保只能通过 getInstance 获取单例
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

private:
    // 私有构造函数,防止外部实例化
    Singleton() {}

    // 静态成员变量和互斥量
    static Singleton* instance;
    static std::mutex mutex;
};

// 静态成员变量的定义
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mutex;

int main() {
    Singleton& s1 = Singleton::getInstance();
    Singleton& s2 = Singleton::getInstance();

    // s1 和 s2 是同一个实例
    std::cout << (&s1 == &s2) << std::endl; // 输出 1

    return 0;
}

在这个示例中,双重检查锁定的方式可以减少每次调用 getInstance() 方法时加锁的开销,提高性能。

 

— – – – > > >  更多设计模式的内容,请看这里