[设计模式]单例模式
简介
单例模式(Singleton Pattern)保证一个类只有一个实例,并提供一个访问它的全局访问点。
单例模式是一种对象创建型模式 (可参考 设计模式 创建型模式)。
结构
图-单例模式结构图
动机
在以下情况中,可以考虑应用单例模式:
- 保证一个类只有一个实例,并提供一个访问它的全局访问点。
- 当唯一的实例应该对子类可扩展,并且用户应该可以在不改变代码的情况下使用扩展的实例。
实际应用场景
在计算机系统中,需要管理的资源包括软件外部资源,譬如每台计算机可以有若干个打印机,但只能有一个Printer Spooler, 以避免两个打印作业同时输出到打印机中。
每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。任务管理器中难以启动两个相同的task。
要点
1、一个类只能有一个实例。
2、实例必须由类自行创建。
3、必须提供获取实例的方法。
实例
1、懒汉式
instance 初始时没有初始化,只有当第一次调 getInstance() 时才创建实例。
继续向下执行,会生成两个实例,违背了单例模式的初衷。
private LazySingleton() {
System.out.println("Singleton()");
}
private static LazySingleton instance = null;
public static LazySingleton getInstance() {
if (null == instance) {
instance = new LazySingleton();
}
return instance;
}
}
2、饿汉式
饿汉根本等不及别人来找他,不管三七二十一先初始化了自身的实例,生怕自己饿着了。
类默认先直接初始化一个实例,以后调用 getInstance() 总是返回这个已创建好的实例。
缺点:在没有必要获取实例时,已经预先产生了开销。
private HungerSinleton() {
System.out.println("Singleton()");
}
private static HungerSinleton instance = new HungerSinleton();
public static HungerSinleton getInstance() {
return instance;
}
}
3、双重锁的形式
如果既不想在没有调用 getInstance() 方法时产生开销,又不想发生线程安全问题,就可以采用双重锁的形式。
private SyncSingleton() {
System.out.println("Singleton()");
}
private static SyncSingleton instance = null;
public static SyncSingleton getInstance() {
if (null == instance) {
synchronized(SyncSingleton.class) {
if (null == instance) {
instance = new SyncSingleton();
}
}
}
return instance;
}
}
注:在外面判断了instance实例是否存在,为什么在锁定后又要在内部又判断一次?
这是因为,如果 instance 为 null 时有两个线程同时调用 getInstance(),由于 synchronized 机制,只有一个线程可以进入,另一个需要等待。
这时如果没有第二道 instance 是否为 null 的判断,就可能发生第一个线程创建一个实例,而第二个线程又创建一个实例的情况。
C++版单例模式
下面是一个采用饿汉式的例子
#include <iostream>
using namespace std;
class Singleton
{
private:
static Singleton *m_instance;
Singleton()
{
cout << "Singleton Construct" << endl;
}
public:
static Singleton* GetInstance()
{
return m_instance;
}
};
Singleton* Singleton::m_instance = new Singleton();
int main()
{
//Singleton *pSingletonA = new Singleton; //编译会报错,因为不能访问私有函数
Singleton *pSingletonA = Singleton::GetInstance();
Singleton *pSingletonB = Singleton::GetInstance();
if (pSingletonA == pSingletonB)
cout << "Same Instance" << endl;
return 0;
}
作者:静默虚空
欢迎任何形式的转载,但请务必注明出处。
限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~