一.前言
单例模式(Singleton Pattern)是一种创建型设计模式,它保证一个类只有一个实例,并提供一个全局访问点,任何尝试创建新实例的操作都会返回同一个实例。这可以避免由于多个实例造成的资源浪费或数据不一致等问题,并且可以方便地访问该实例。
1.为什么需要单例模式
- 需要在系统中全局共享一个对象,而不希望被重复创建多个实例。
- 需要对一些共享的资源进行管理,例如线程池、数据库连接池等。
- 需要对某些对象进行控制,例如日志记录器、缓存、配置文件等。
- 需要保证系统中某个实例的唯一性,例如系统中的计数器。
2.实现方法
- 实现单例模式的方法通常包括使用静态变量、私有构造函数和静态方法等技术,以确保只有一个实例被创建并且可以被全局访问。 单例模式主要
- 懒汉模式和饿汉模式都是实现单例模式的方法,它们的主要区别在于对象的创建时机不同。
二.懒汉模式——在需要使用对象时才进行实例化,而不是在程序启动时就进行实例化
1.优缺点
1.优点 | 2.缺点 |
---|
1. 延迟加载,避免了不必要的资源占用。 | 1. 存在线程安全问题,需要进行同步处理,降低了程序的效率。 |
2. 在需要的时候才进行实例化,提高了程序的效率。 | 2. 代码实现比较复杂,容易出错。 |
2.适用场景
- 对象的创建较为耗时,需要延迟加载,例如数据库连接池、网络连接等。
- 需要控制对象的创建时机,避免不必要的资源浪费。
- 数据库连接池、线程池等资源的创建等
3.C++程序示例
#include <iostream>
#include <mutex>
class Singleton {
public:
static Singleton* getInstance() {
if (instance_ == nullptr) {
std::lock_guard<std::mutex> lock(mutex_);
if (instance_ == nullptr) {
instance_ = new Singleton();
}
}
return instance_;
}
private:
Singleton() {
std::cout << "Singleton instance created!" << std::endl;
}
~Singleton() {
std::cout << "Singleton instance destroyed!" << std::endl;
}
static Singleton* instance_;
static std::mutex mutex_;
};
Singleton* Singleton::instance_ = nullptr;
std::mutex Singleton::mutex_;
int main() {
Singleton* instance1 = Singleton::getInstance();
Singleton* instance2 = Singleton::getInstance();
if (instance1 == instance2) {
std::cout << "instance1 and instance2 are the same instance!" << std::endl;
}
else {
std::cout << "instance1 and instance2 are different instances!" << std::endl;
}
return 0;
}
- 在懒汉模式的实现中,使用了双检锁机制(Double-Checked
Locking),即在检查指针是否为空之前先获取互斥锁,以确保线程安全。 - 在单例类的实现中,将构造函数和析构函数设置为私有,防止外部直接创建和销毁实例。使用静态成员变量保存唯一实例的指针,使用互斥量保证线程安全。
- 在 main 函数中,获取单例对象并验证是否只有一个实例被创建。
二.饿汉模式——在程序启动时就进行实例化,而不是在需要使用对象时才进行实例化
1.优缺点
1.优点 | 2.缺点 |
---|
1. 实现简单,线程安全,不需要进行同步处理。 | 1. 可能会占用过多的资源。 |
2. 对象在程序启动时就已经实例化,提高了程序的效率。 | 2. 在程序启动时就进行实例化,可能会导致不必要的资源浪费。 |
2.适用场景
- 对象的创建比较简单,不需要进行复杂的初始化操作。
- 程序启动时就需要使用该对象,而且该对象不会占用过多的资源。
- 系统配置信息、日志记录器等资源的创建等。
3.C++程序示例
#include <iostream>
class Singleton {
public:
static Singleton* getInstance() {
return instance_;
}
private:
Singleton() {
std::cout << "Singleton instance created!" << std::endl;
}
~Singleton() {
std::cout << "Singleton instance destroyed!" << std::endl;
}
static Singleton* instance_;
};
Singleton* Singleton::instance_ = new Singleton();
int main() {
Singleton* instance1 = Singleton::getInstance();
Singleton* instance2 = Singleton::getInstance();
if (instance1 == instance2) {
std::cout << "instance1 and instance2 are the same instance!" << std::endl;
}
else {
std::cout << "instance1 and instance2 are different instances!" << std::endl;
}
return 0;
}
- 在饿汉模式的实现中,使用了静态成员变量来保存唯一实例的指针,并在类加载时就完成了初始化,保证了线程安全。
- 在单例类的实现中,同样将构造函数和析构函数设置为私有,防止外部直接创建和销毁实例。
- 在
main
函数中,获取单例对象并验证是否只有一个实例被创建。相比于懒汉模式,饿汉模式的实现更为简单,但可能会影响程序的启动时间,因为实例在程序启动时就已经创建了。