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

相关推荐
柒七爱吃麻辣烫14 分钟前
在Linux中安装JDK并且搭建Java环境
java·linux·开发语言
fallzzzzz15 分钟前
C++ stl中的list的相关函数用法
c++·list
极小狐26 分钟前
如何构建容器镜像并将其推送到极狐GitLab容器镜像库?
开发语言·数据库·机器学习·gitlab·ruby
多多*1 小时前
Java反射 八股版
java·开发语言·hive·python·sql·log4j·mybatis
正在走向自律1 小时前
从0到1:Python机器学习实战全攻略(8/10)
开发语言·python·机器学习
悦悦子a啊1 小时前
PTA:jmu-ds-最短路径
c++·算法·图论
FY_20182 小时前
键盘输出希腊字符方法
开发语言
西西弗Sisyphus2 小时前
Python 处理图像并生成 JSONL 元数据文件 - 灵活text版本
开发语言·python
小王努力学编程2 小时前
高并发内存池(三):TLS无锁访问以及Central Cache结构设计
jvm·数据结构·c++·学习
q567315232 小时前
Go语言多线程爬虫与代理IP反爬
开发语言·爬虫·tcp/ip·golang