文章目录
- 一.什么是单例设计模式?
- 二.单例模式的特点
- 三.单例模式的结构
- 四.单例模式的优缺点
- [五.单例模式的 C++ 实现](#五.单例模式的 C++ 实现)
- [六.单例模式的 Java 实现](#六.单例模式的 Java 实现)
- 七.代码解析
- 八.总结
类图: 单例设计模式类图
一.什么是单例设计模式?
单例设计模式 (Singleton Pattern) 是一种创建型设计模式,旨在确保一个类只有一个实例,并提供一个全局访问点来访问该实例。单例模式通过控制实例的创建过程,避免了重复实例化的开销,常用于全局管理的场景。
二.单例模式的特点
- 唯一性:单例模式确保一个类只有一个实例。
- 全局访问点:通过提供一个静态方法获取唯一实例,方便全局访问。
- 延迟初始化:通常单例实例在第一次使用时初始化,优化性能。
三.单例模式的结构
- Singleton(单例类) :实现唯一实例的创建逻辑,并提供全局访问方法。
四.单例模式的优缺点
- 优点:
- 唯一性保证:确保全局范围内只有一个实例,避免资源浪费。
- 全局访问:通过统一接口提供访问,简化代码调用。
- 控制实例生命周期:控制实例的创建和销毁,防止多个实例干扰。
- 缺点:
- 多线程复杂性:在多线程环境下需要额外处理线程安全问题。
- 不易扩展:单例模式本质上限制了类的扩展性。
- 隐藏依赖:可能导致全局状态被意外修改,影响代码可维护性。
五.单例模式的 C++ 实现
cpp
#include <iostream>
#include <mutex>
using namespace std;
// 单例类
class Singleton {
private:
static Singleton* instance; // 静态实例指针
static mutex mtx; // 用于线程安全的互斥锁
// 私有构造函数,防止外部实例化
Singleton() {
cout << "Singleton instance created!" << endl;
}
// 禁止拷贝构造和赋值操作
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public:
// 静态方法获取唯一实例
static Singleton* GetInstance() {
if (instance == nullptr) { // 检查是否已经存在实例
lock_guard<mutex> lock(mtx); // 加锁以确保线程安全
if (instance == nullptr) { // 双重检查锁定
instance = new Singleton();
}
}
return instance;
}
// 示例方法
void ShowMessage() {
cout << "Hello from Singleton instance!" << endl;
}
// 销毁单例实例(可选)
static void DestroyInstance() {
lock_guard<mutex> lock(mtx);
if (instance) {
delete instance;
instance = nullptr;
cout << "Singleton instance destroyed!" << endl;
}
}
};
// 初始化静态成员
Singleton* Singleton::instance = nullptr;
mutex Singleton::mtx;
// 测试单例模式
int main() {
Singleton* s1 = Singleton::GetInstance();
s1->ShowMessage();
Singleton* s2 = Singleton::GetInstance();
s2->ShowMessage();
// 销毁实例(如果需要手动释放内存)
Singleton::DestroyInstance();
return 0;
}
六.单例模式的 Java 实现
java
public class Singleton {
// 静态实例变量
private static Singleton instance;
// 私有构造函数,防止外部实例化
private Singleton() {
System.out.println("Singleton instance created!");
}
// 公共静态方法获取唯一实例(线程安全)
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
// 示例方法
public void showMessage() {
System.out.println("Hello from Singleton instance!");
}
public static void main(String[] args) {
Singleton s1 = Singleton.getInstance();
s1.showMessage();
Singleton s2 = Singleton.getInstance();
s2.showMessage();
}
}
七.代码解析
- 静态成员变量 :
- Singleton* instance 是一个静态指针,用于保存单例类的唯一实例。
- 静态变量保证在全局范围内只存在一个实例。
- 私有构造函数 :
- 构造函数被声明为 private,禁止外部通过 new 关键字创建实例。
- 通过控制实例化的入口,保证类的唯一性。
- 线程安全 :
- 使用 mutex 和 lock_guard 确保在多线程环境下访问 GetInstance 是安全的。
- 实现了双重检查锁定(Double-Checked Locking)机制,以避免不必要的锁开销。
- 双重检查锁定 :
- 第一次检查 if (instance == nullptr),快速跳过锁定代码,提高性能。
- 第二次检查是为了确保实例在加锁后没有被其他线程创建。
- 静态方法 GetInstance :
- 这是访问单例实例的唯一入口,通过静态方法确保全局访问性。
- 如果实例不存在,则创建;如果已存在,则直接返回。
- 销毁单例 :
- 提供了 DestroyInstance 方法,用于手动释放单例实例的内存。
- 销毁操作同样需要加锁以保证线程安全。
八.总结
单例模式是一种简单而实用的设计模式,常用于需要全局唯一实例的场景。C++ 中实现单例模式需要特别注意线程安全和内存管理,而 Java 则通过 synchronized 关键字简化了多线程支持。
单例模式虽然解决了很多全局共享资源的问题,但需要注意避免过度使用,因为全局状态可能会导致代码难以测试和维护。
应用场景:
- 全局配置管理:如应用程序的配置类或日志管理器。
- 资源共享:如数据库连接池、线程池等需要共享资源的场景。
- 控制全局访问:如访问计数器或全局缓存管理器。