设计模式-01 设计模式单例模式

发布于:2024-05-08 ⋅ 阅读:(27) ⋅ 点赞:(0)
设计模式-01 设计模式单例模式

目录

设计模式-01 设计模式单例模式

1定义

2.内涵

3.使用示例

4.具体代码使用实践

5.注意事项

6.最佳实践

7.总结


1 定义


单例模式是一种设计模式,它确保一个类只能被实例化一次。它通过在类内部创建类的唯一实例并提供一个全局访问点来实现这一点。


优点:

全局访问:单例对象可以从应用程序的任何地方访问。
资源节约:它只创建一个对象,从而节省了内存和资源。
线程安全性:如果单例对象正确实现,它可以是线程安全的,这意味着它可以在多线程环境中安全地使用。


2.内涵

单例模式在 C++ 设计模式中具有以下内涵:

封装:单例类的内部状态和实现细节对客户端代码是隐藏的。这使你可以自由地更改类的实现,而无需影响使用它的代码。
全局访问:单例对象可以在应用程序的任何地方访问,这使得它非常适合存储全局状态或提供公共服务。
资源管理:由于单例模式确保只创建一个对象,因此它可以帮助管理资源,例如数据库连接或文件句柄。

3.使用示例

单例模式,有很多种实现方式,下面是几种实现方式的介绍。

延迟加载

class Singleton {
private:
    static Singleton* instance;
    Singleton() {}

public:
    static Singleton* getInstance() {
        if (instance == nullptr) {
            instance = new Singleton();
        }
        return instance;
    }
};


饿汉式

class Singleton {
private:
    static Singleton* instance = new Singleton();
    Singleton() {}

public:
    static Singleton* getInstance() {
        return instance;
    }
};

C++11 实现单例模式代码

class Singleton {
private:
    Singleton() {}  // 私有构造函数防止直接实例化
    Singleton(const Singleton&) = delete;  // 私有拷贝构造函数防止复制
    Singleton& operator=(const Singleton&) = delete;  // 私有赋值运算符防止赋值

    static Singleton* instance;  // 静态成员变量存储单例实例

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

private:
    static std::mutex mutex;  // 互斥锁用于线程安全
};

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

4.具体代码使用实践
#include <iostream>
 
class Singleton {
public:
    // Static method to access the singleton instance
    static Singleton& getInstance()
    {
        // If the instance doesn't exist, create it
        if (!instance) {
            instance = new Singleton();
        }
        return *instance;
    }
 
    // Public method to perform some operation
    void someOperation()
    {
        std::cout
            << "Singleton is performing some operation."
            << std::endl;
    }
 
    // Delete the copy constructor and assignment operator
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
 
private:
    // Private constructor to prevent external instantiation
    Singleton()
    {
        std::cout << "Singleton instance created."
                  << std::endl;
    }
 
    // Private destructor to prevent external deletion
    ~Singleton()
    {
        std::cout << "Singleton instance destroyed."
                  << std::endl;
    }
 
    // Private static instance variable
    static Singleton* instance;
};
 
// Initialize the static instance variable to nullptr
Singleton* Singleton::instance = nullptr;
 
int main()
{
    // Access the Singleton instance
    Singleton& singleton = Singleton::getInstance();
 
    // Use the Singleton instance
    singleton.someOperation();
 
    // Attempting to create another instance will not work
    // Singleton anotherInstance; // This line would not
    // compile
 
    return 0;
}

5.注意事项


C++11 实现单例模式的注意事项和潜在问题:

1. 线程安全性:

确保单例类的实现是线程安全的,以避免并行访问时出现数据损坏。使用互斥锁或其他同步机制来保护共享数据。


2. 静态局部变量初始化顺序未定义:

在 C++11 中,静态局部变量(例如 Singleton::instance)的初始化顺序是未定义的。为了确保单例类的正确初始化,请使用双重检查锁定模式。


3. 循环引用和内存泄漏:

如果单例类持有其他对象的引用,请确保这些引用不会导致循环引用并导致内存泄漏。可以使用智能指针或弱引用来管理引用。


4. 异常安全性:

单例类的构造函数应该抛出异常安全,这意味着在构造函数抛出异常后,单例类的状态应该保持有效。可以使用 RAII 技术来实现异常安全性。


5. 过度使用:

避免过度使用单例模式。只在需要全局访问和资源管理的情况下才使用它。过度使用单例模式可能会导致设计僵化和测试困难。

6.最佳实践
  • 使用双重检查锁定:这是一种可靠的方法来确保线程安全的单例实现。
  • 使用 RAII 技术:这可以确保在异常情况下正确清理资源。
  • 仔细管理引用:使用智能指针或弱引用来避免循环引用和内存泄漏。
  • 仅在必要时使用单例模式:考虑其他设计模式,例如工厂模式或依赖注入,以实现全局访问和资源管理。
  • 进行彻底的测试:编写测试用例来验证单例实现的正确性和线程安全性。

7.总结

C++11 中的单例模式通过双重检查锁定和 RAII 技术实现线程安全的惰性实例化,确保全局访问和资源管理。在实现上,这比起低版本的来说,预言特性给我们更加灵活的操作性