C++单例模式与多例模式

C++ 单例模式的设计意图

单例模式(Singleton Pattern) 是一种创建型设计模式,其主要目的是确保一个类只有一个实例,并提供一个全局访问点。单例模式常用于需要全局唯一实例的场景,例如:

  1. 日志记录器:在整个应用程序中,只需要一个日志记录器实例来记录所有的日志信息。
  2. 配置管理器:应用程序的配置信息通常只需要一个实例来管理。
  3. 数据库连接池:在整个应用程序中,只需要一个数据库连接池实例来管理数据库连接。

单例模式的实现方式

单例模式的实现方式主要有两种:懒汉式(Lazy Initialization)饿汉式(Eager Initialization)

懒汉型单例模式

懒汉式单例模式在第一次使用时才创建实例,因此它具有延迟加载的特性。如果单例对象的创建成本较高,懒汉式可以在需要时才进行创建,从而提高性能。

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

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

    // 构造函数私有化,防止外部创建实例
    Singleton() {
        std::cout << "Singleton instance created." << std::endl;
    }

public:
    // 获取单例实例
    static Singleton* getInstance() {
        // 双重检查锁定,确保线程安全
        if (instance == nullptr) {
            std::lock_guard<std::mutex> lock(mtx);
            if (instance == nullptr) {
                instance = new Singleton();
            }
        }
        return instance;
    }

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

    // 销毁实例
    static void destroyInstance() {
        delete instance;
        instance = nullptr;
    }

    // 测试方法
    void showMessage() {
        std::cout << "Hello from Singleton!" << std::endl;
    }
};

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

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

    s1->showMessage();
    s2->showMessage();

    if (s1 == s2) {
        std::cout << "s1 and s2 are the same instance." << std::endl;
    } else {
        std::cout << "s1 and s2 are different instances." << std::endl;
    }

    Singleton::destroyInstance();
    return 0;
}

饿汉型单例模式

饿汉式单例模式在程序启动时就创建实例,而不是在第一次使用时创建。由于实例在程序启动时就创建,因此它的实现相对简单,不需要考虑线程安全问题。

cpp 复制代码
#include <iostream>

class Singleton {
private:
    static Singleton* instance;

    // 构造函数私有化,防止外部创建实例
    Singleton() {
        std::cout << "Singleton instance created." << std::endl;
    }

public:
    // 获取单例实例
    static Singleton* getInstance() {
        return instance;
    }

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

    // 销毁实例
    static void destroyInstance() {
        delete instance;
        instance = nullptr;
    }

    // 测试方法
    void showMessage() {
        std::cout << "Hello from Singleton!" << std::endl;
    }
};

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

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

    s1->showMessage();
    s2->showMessage();

    if (s1 == s2) {
        std::cout << "s1 and s2 are the same instance." << std::endl;
    } else {
        std::cout << "s1 and s2 are different instances." << std::endl;
    }

    Singleton::destroyInstance();
    return 0;
}

多线程安全版单例模式

多线程安全的单例模式通常采用**双重检查锁定(Double-Checked Locking)**技术,确保在多线程环境下只有一个实例被创建。

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

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

    // 构造函数私有化,防止外部创建实例
    Singleton() {
        std::cout << "Singleton instance created." << std::endl;
    }

public:
    // 获取单例实例
    static Singleton* getInstance() {
        // 双重检查锁定,确保线程安全
        if (instance == nullptr) {
            std::lock_guard<std::mutex> lock(mtx);
            if (instance == nullptr) {
                instance = new Singleton();
            }
        }
        return instance;
    }

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

    // 销毁实例
    static void destroyInstance() {
        delete instance;
        instance = nullptr;
    }

    // 测试方法
    void showMessage() {
        std::cout << "Hello from Singleton!" << std::endl;
    }
};

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

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

    s1->showMessage();
    s2->showMessage();

    if (s1 == s2) {
        std::cout << "s1 and s2 are the same instance." << std::endl;
    } else {
        std::cout << "s1 and s2 are different instances." << std::endl;
    }

    Singleton::destroyInstance();
    return 0;
}

总结

  • 懒汉式单例模式:在第一次使用时创建实例,适用于实例创建成本较高的情况,但需要考虑线程安全问题。
  • 饿汉式单例模式:在程序启动时创建实例,实现简单,线程安全,但可能会导致资源浪费。
  • 多线程安全版单例模式:通过双重检查锁定技术确保在多线程环境下只有一个实例被创建。

C++ 多例模式示例代码

多例模式(Multiton Pattern) 是单例模式的一种扩展,它允许多个实例,每个实例都有一个唯一的标识符(例如名称)。通过这种方式,可以在需要多个唯一实例的情况下使用多例模式。

在下面的示例中,我们将创建一个多例模式,使用 std::map 来存储实例和它们的名称。我们将创建固定数量的实例,并在需要时通过名称来获取它们。

代码示例

cpp 复制代码
#include <iostream>
#include <map>
#include <string>
#include <memory>

class Multiton {
private:
    // 实例名称
    std::string name;

    // 构造函数私有化,防止外部创建实例
    Multiton(const std::string& name) : name(name) {
        std::cout << "Multiton instance created: " << name << std::endl;
    }

    // 静态成员变量,用于存储多例实例
    static std::map<std::string, std::shared_ptr<Multiton>> instances;

public:
    // 获取多例实例
    static std::shared_ptr<Multiton> getInstance(const std::string& name) {
        auto it = instances.find(name);
        if (it == instances.end()) {
            // 如果实例不存在,创建并存储它
            std::shared_ptr<Multiton> instance = std::make_shared<Multiton>(name);
            instances[name] = instance;
            return instance;
        }
        return it->second;
    }

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

    // 测试方法
    void showMessage() {
        std::cout << "Hello from Multiton " << name << "!" << std::endl;
    }
};

// 静态成员变量初始化
std::map<std::string, std::shared_ptr<Multiton>> Multiton::instances;

int main() {
    // 创建固定数量的实例,每个实例有一个名称
    std::shared_ptr<Multiton> m1 = Multiton::getInstance("Instance1");
    std::shared_ptr<Multiton> m2 = Multiton::getInstance("Instance2");
    std::shared_ptr<Multiton> m3 = Multiton::getInstance("Instance3");

    // 获取已经创建的实例
    std::shared_ptr<Multiton> m4 = Multiton::getInstance("Instance1");
    std::shared_ptr<Multiton> m5 = Multiton::getInstance("Instance2");
    std::shared_ptr<Multiton> m6 = Multiton::getInstance("Instance3");

    // 测试方法调用
    m1->showMessage();
    m2->showMessage();
    m3->showMessage();
    m4->showMessage();
    m5->showMessage();
    m6->showMessage();

    // 检查实例是否相同
    if (m1 == m4 && m2 == m5 && m3 == m6) {
        std::cout << "The instances are the same." << std::endl;
    } else {
        std::cout << "The instances are different." << std::endl;
    }

    return 0;
}

代码说明

  1. 私有构造函数Multiton 类的构造函数是私有的,防止外部直接创建实例。
  2. 静态成员变量 instances :使用 std::map 存储实例名称和对应的实例指针。
  3. getInstance 方法:通过名称获取实例。如果实例不存在,则创建并存储它。
  4. showMessage 方法:用于测试实例是否正常工作。

输出结果

运行上述代码后,输出结果将显示每个实例的创建信息,并验证通过相同名称获取的实例是否相同。

cpp 复制代码
Multiton instance created: Instance1
Multiton instance created: Instance2
Multiton instance created: Instance3
Hello from Multiton Instance1!
Hello from Multiton Instance2!
Hello from Multiton Instance3!
Hello from Multiton Instance1!
Hello from Multiton Instance2!
Hello from Multiton Instance3!
The instances are the same.

总结

多例模式通过 std::map 存储多个实例,每个实例都有一个唯一的标识符(例如名称)。通过这种方式,可以在需要多个唯一实例的情况下使用多例模式,并且可以方便地通过标识符获取实例。

相关推荐
芥子沫1 小时前
VSCode添加Python、Java注释技巧、模板
开发语言·前端·javascript
小陈又菜1 小时前
【C++】类和对象--类中6个默认成员函数(2) --运算符重载
开发语言·c++·运算符重载
yuezhilangniao1 小时前
关于开发语言的一些效率 从堆栈角度理解一部分c java go python
java·c语言·开发语言
Ares-Wang2 小时前
Node.js 》》bcryptjs 加密
开发语言·javascript·node.js
vvilkim2 小时前
深入理解Java访问修饰符:封装的艺术
java·开发语言
最爱吃南瓜2 小时前
JS逆向实战案例之----【通姆】252个webpack模块自吐
开发语言·javascript·爬虫·webpack·js逆向·算法模拟
hqxstudying3 小时前
java分布式定时任务
java·开发语言·分布式
weixin_307779134 小时前
C++实现MATLAB矩阵计算程序
开发语言·c++·算法·matlab·矩阵
捏尼卜波卜4 小时前
try/catch/throw 简明指南
linux·开发语言·c++
_poplar_5 小时前
09 【C++ 初阶】C/C++内存管理
c语言·开发语言·数据结构·c++·git·算法·stl