单例模式(Singleton Pattern)是一种设计模式,它确保一个类只有一个实例,并提供一个全局访问点。单例模式在需要控制实例数目的场景中非常有用,例如管理数据库连接或日志记录。
以下是一个简单的 C++ 单例模式的示例代码:
懒汉式单例模式
懒汉式单例模式在第一次使用时才会创建实例。
#include <iostream>
#include <mutex>
class Singleton
{
public:
// 获取单例实例的静态方法
static Singleton& getInstance()
{
// 使用局部静态变量确保线程安全
static Singleton instance;
return instance;
}
// 删除拷贝构造函数和赋值运算符,防止复制实例
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
// 示例方法
void showMessage()
{
std::cout << "Welcome to Singleton!" << std::endl;
}
private:
// 私有构造函数,防止外部实例化
Singleton() { }
};int main()
{
// 获取单例实例并调用方法
Singleton& singleton = Singleton::getInstance();
singleton.showMessage();
return 0;
}
饿汉式单例模式
饿汉式单例模式在程序启动时就创建实例。
#include <iostream>class Singleton
{
public:
// 获取单例实例的静态方法
static Singleton& getInstance()
{
return instance;
}
// 删除拷贝构造函数和赋值运算符,防止复制实例
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
// 示例方法
void showMessage()
{
std::cout << "Welcome to Singleton!" << std::endl;
}
private:
// 私有构造函数,防止外部实例化
Singleton() { }
// 静态实例
static Singleton instance;
};
// 初始化静态实例
Singleton Singleton::instance;int main()
{
// 获取单例实例并调用方法
Singleton& singleton = Singleton::getInstance();
singleton.showMessage();
return 0;
}
线程安全的懒汉式单例模式
为了确保线程安全,可以使用互斥锁(mutex)。
#include <iostream>
#include <mutex>
class Singleton
{
public:
// 获取单例实例的静态方法
static Singleton& getInstance()
{
std::call_once(initInstanceFlag, &Singleton::initSingleton);
return *instance;
}
// 删除拷贝构造函数和赋值运算符,防止复制实例
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
// 示例方法
void showMessage()
{
std::cout << "Welcome to Singleton!" << std::endl;
}
private:
// 私有构造函数,防止外部实例化
Singleton() { }
// 初始化单例实例的私有方法
static void initSingleton()
{
instance = new Singleton();
}
// 静态实例指针
static Singleton* instance;
// 用于线程安全的 once_flag
static std::once_flag initInstanceFlag;
};
// 初始化静态成员
Singleton* Singleton::instance = nullptr;
std::once_flag Singleton::initInstanceFlag;
int main()
{
// 获取单例实例并调用方法
Singleton& singleton = Singleton::getInstance();
singleton.showMessage(); return 0;
}
总结
以上代码展示了三种单例模式的实现方式:懒汉式、饿汉式和线程安全的懒汉式。每种方式都有其适用的场景,可以根据实际需求选择合适的实现方式。
懒汉式单例模式
适用场景:
-
延迟初始化:当单例实例的创建开销较大,且不一定会在程序运行期间使用时,懒汉式可以避免不必要的开销。
-
内存敏感的应用:在内存资源有限的环境中,懒汉式可以避免在程序启动时就占用内存。
-
单线程环境:在单线程环境中,懒汉式实现简单且无需考虑线程安全问题。
饿汉式单例模式
适用场景:
-
确定会使用单例实例:如果在程序运行期间肯定会使用单例实例,饿汉式可以确保实例在程序启动时就创建,避免第一次访问时的延迟。
-
线程安全:饿汉式在程序启动时就创建实例,天然是线程安全的,不需要额外的同步机制。
-
性能优先:在性能敏感的应用中,饿汉式可以避免懒汉式第一次访问时的加锁开销。
线程安全的懒汉式单例模式适用场景:
适用场景:
-
多线程环境:在多线程环境中,需要确保单例实例的创建是线程安全的,以避免多个线程同时创建多个实例。
-
延迟初始化:与懒汉式相同,适用于单例实例的创建开销较大且不一定会使用的场景,但需要线程安全保证。
-
复杂初始化:如果单例实例的初始化过程较为复杂,且需要控制初始化时机,线程安全的懒汉式可以提供更灵活的控制。