C++ 设计模式之单例模式
简介
1、单例模式是一种创建型模式,它确保一个类只有一个实例,并提供一个全局访问点来获取该实例。这种模式的主要目的是减少系统资源的消耗,提高系统的性能和安全性。
2、单例模式 (Singleton)应用场景包括但不限于:
2.1、配置文件管理 :当程序只需要从单一的全局配置读取设置时,可以使用单例来管理配置文件的读取。
2.2、数据库连接池 :单例模式可以用于维护数据库连接池,确保全局只有一个数据库连接池,从而减少数据库连接的开销。
2.3、日志记录器 :使用单例模式来构建日志记录器,保证全局只有一个日志写入实例,避免在写入日志时出现的冲突。
2.4、硬件接口访问 :当系统中的硬件资源只能被一个实例占用时,使用单例可以防止资源冲突。
2.5、应用程序的全局状态或服务 :用于全局状态的维护或者作为全局服务提供器,比如全局缓存、窗口管理器等。
3、单例模式的实现方式有多种,包括饿汉式和懒汉式。
3.1、饿汉式单例模式在类加载时就创建了实例。
3.2、懒汉式单例模式则是在首次使用时才创建实例。懒汉式单例模式又可以分为原始懒汉式、双重检查锁、volatile防止指令重排、静态内部类等方式,以应对多线程环境下的安全问题。
3.2.1、原始懒汉式
懒汉式单例模式在第一次调用getInstance()方法时创建实例。这种方式在并发环境下可能会遇到线程安全问题
public:
static Singleton* getInstance()
{
if (!instance)
{
instance = new Singleton();
}
return instance;
}
3.2.2、双重检查锁
双重检查锁是为了解决原始懒汉式在多线程环境下的线程安全问题而设计的。它在getInstance()方法内部使用了双重检查,以确保只创建一个实例
private:
static std::weak_ptr<Singleton> instance;
static std::mutex mtx;
public:
static std::shared_ptr<Singleton> getInstance()
{
std::shared_ptr<Singleton> localInstance = instance.lock();
if (!localInstance) // 第一次检查
{
std::lock_guard<std::mutex> lock(mtx);
localInstance = instance.lock();
if (!localInstance) // 第二次检查
{
localInstance = std::shared_ptr<Singleton>(new Singleton());
instance = localInstance;
}
}
return localInstance;
}
3.2.3、静态内部类
只有在第一次调用getInstance()方法时才会被创建
public:
static Singleton& getInstance()
{
static Singleton instance
return &instance;
}
4、单例模式的优点包括减少内存开支、减少系统性能开销、避免资源的多重占用等。然而,它也有一些缺点,如扩展困难、测试不便等
示例
定义
class Singleton
{
private:
// 私有静态指针变量,指向类的唯一实例
static Singleton* instance;
// 私有构造函数,不允许外部直接创建实例
Singleton() {};
// 禁用拷贝构造函数和赋值操作符
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
static Singleton* getInstance();
void doSomething();
};
实现
Singleton* Singleton::instance = nullptr;
Singleton* Singleton::getInstance()
{
if (instance == nullptr)
{
instance = new Singleton();
}
return instance;
}
void Singleton::doSomething()
{
std::cout << "这是一个单例模式" << std::endl;
}
调用
auto singleton = Singleton::getInstance();
singleton->doSomething();