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 分钟前
【字符串】给定一个字符串 text 和字符串列表 words,返回 words 中每个单词在 text 中的位置(要求最终的位置从小到大进行排序)
开发语言·数据结构·python
攻城丶狮5 分钟前
信息学奥赛-一本通-第二部分 基础算法 --> 第五章 搜索与回溯算法
c++·算法·青少年编程·深度优先·图论
凡人的AI工具箱8 分钟前
15分钟学 Go 第 59 天 :更高级的Go话题——接触微服务
开发语言·人工智能·后端·微服务·golang
喻师傅15 分钟前
Scala-注释、标识符、变量与常量-用法详解
大数据·开发语言·scala
小白的白是白痴的白19 分钟前
11.14 Scala的Array
开发语言·后端·scala
未知陨落20 分钟前
数据结构——红黑树
开发语言·数据结构·c++·红黑树
赛丽曼37 分钟前
Python中的进程和线程
开发语言·python
繁星璀璨G40 分钟前
C++11标准模板(STL)- 算法 - 对一个范围内的拥有一定未指定类型的元素排序(qsort, qsort_s)
开发语言·c++·算法·stl·常用数学函数
想不到好名字了()1 小时前
个人C++复习(3)
开发语言·c++
DashVector1 小时前
如何使用DashVector的多向量检索
开发语言·数据库·人工智能·数据库架构