前言
最近在写项目的时候用到单例模式,之前只是简单的使用。在 C++ 中,实现单例模式的方法有多种,今天对单例模式做一个深度的总结与对比,将介绍单例模式的原理、实现方法以及各种方法的优缺点。
一、单例模式的原理
单例模式是一种常用的设计模式,用于保证一个类只有一个实例存在,并提供一个全局访问点。
单例模式的核心思想是让一个类只能创建一个实例,并提供一个全局访问点,以便在程序中任何地方都可以访问该实例。在 C++ 中,可以通过以下步骤来实现单例模式:定义静态成员变量的目的是为了保存单例对象,使得工厂方法能够返回这个唯一的实例。而将默认构造函数设为私有,则是为了防止外部程序随意创建单例对象。
将类的构造函数设为私有,禁止外部创建实例。
定义一个静态成员变量,用于保存单例对象。
构造一个全局的工厂方法,用于获取单例对象。
简单例子
class Singleton {
public:
static Singleton& getInstance() {
static Singleton instance; // 创建静态变量保存唯一实例
return instance;
}
void printMessage() {
std::cout << "Hello, World!" << std::endl;
}
private:
Singleton() {
} // 将构造函数设为私有,禁止外部创建实例
Singleton(const Singleton&) = delete; // 禁止拷贝构造
Singleton& operator=(const Singleton&) = delete; // 禁止赋值操作
};
int main() {
Singleton& instance1 = Singleton::getInstance();
Singleton& instance2 = Singleton::getInstance();
std::cout << std::boolalpha << (&instance1 == &instance2) << std::endl;
instance1.printMessage(); // 输出 "Hello, World!"
instance2.printMessage(); // 输出 "Hello, World!"
return 0;
}
在上面的例子中,Singleton 类的构造函数被设为私有,禁止外部创建实例。getInstance() 函数返回一个静态的 Singleton 类型变量,用于保存类的唯一实例。由于该变量是静态的,因此只会在程序第一次调用 getInstance() 函数时被创建。
在 main() 函数中,我们分别通过 Singleton::getInstance() 函数获取两个 Singleton 类型的实例 instance1 和 instance2。由于 Singleton 类只有一个实例,因此我们可以使用地址比较运算符 & 来验证它们是否是同一个实例。最后,我们通过 instance1 和 instance2 分别调用 Singleton 类的成员函数 printMessage(),输出 “Hello, World!”。
二、实现单例模式的几种方法
单例模式有两种类型:
懒汉式:在真正需要使用对象时才去创建该单例类对象
饿汉式:在类加载时已经创建好该单例对象,等待被程序使用
1.加锁的懒汉式
加锁的懒汉式是指在第一次调用 getInstance() 函数时,通过加锁的方式来保证线程安全。如果实例还没有被创建,则创建实例并返回实例的指针;如果实例已经被创建,则直接返回实例的指针。以下是一个加锁的懒汉式的实现: