设计模式学习笔记十:单例模式(Singleton Pattern)
1.概述
单例模式(Singleton Pattern)又称单件模式,单例模式保证一个类仅有一个实例,并提供一个访问的他的全局访问点。通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化对个对象,一个最好的办法就是,让类自身负责保存他的唯一实例,这个类可以保证没有其他实例可以被创建并且他可以提供一个访问该实例的方法。
使用场合:当类只能有一个实例存在,并且可以在全局访问时,这个唯一的实例应该可以通过子类实现扩展,并且用户无须更改代码即可使用。前面学习过得工厂类经常被实例化为全局唯一的单件,可能的单件还有系统的管理日志的对象、关键字生成对象和外部设备接口对象等。
结构:


单例模式提供了全局唯一的访问入口,易于控制可能发生的冲突。
单例模式因为Singleton类封装它的唯一实例,这样他可以严格的控制客户怎样访问它以及何时访问他。
单例模式是对静态方法的一种改进,首先避免了全局变量对系统的污染,其次他可以有子类,可以定义虚方法,具有多态性。而类中的静态方法是不能被定义为虚方法,因此不具有多态性。
2.实例
1.单件计数器
最简单的单例模式应用就是计数器,在基于Web的应用中,我们希望有一个全局计数器来统计单件的次数,为此我们要定义一个单件计数器:

调用代码:




在多线程程序中,多个线程同时访问Singleton类时,调用GetInstance()方法,会有可能造成创建多个实例,我们可以给进程加一把锁来处理。锁(Lock)是确保当一个线程位于代码的临界区时,另一个线程不能进入该临界区,如果其他线程试图进入锁定的代码,则他将一直等待(即被阻止),直到该对象被释放【MSDN】。
下面来看加锁的单例模式:

上面的代码中的对象实例由最先进入的那个线程创建,以后的线程在进入时不会再去创建对象实例了。由于有了Lock,就保证了多线程环境下的同时访问也不会造成多个实例的生成。
我们不经要问,为什么不直接lock呢,而是创建一个SyncRoot来Lock呢?因为在我们加锁的时候,instance实例有没有被创建过实例我们都还不知道呢,我们不可能对其加锁的。上面我们=每次调用GetInstance()方法时,都需要Lock,这样会影响性能的。所以我们再做一定的改良优化,看下面的代码:

3.静态初始化
在.Net中公共语言运行库中也提供了一种“静态初始化”方法,这种方法不需要显示的编写线程安全代码,即可解决多线程环境下单例模式不安全的问题.看下面简单的代码:

3.总结
全局变量与单例模式:单例模式维护了自身的实例化,在使用上是安全的,一个全局对象无法自行维护,也就无法规避重复创建对象实例,系统资源会被大量占用,更糟糕的是会出现逻辑问题。
单件与实用类中的静态方法:
实用类是提供系统公用的静态方法,并且也经常采用私有的构造方法,与单例不同,他没有实例,其中的方法全是静态方法。实用类和单例模式的区别如下:
1).实用类不保存状态,仅提供功能。2)实用类不具有多态性,而单例类可以有子类。3)单例是对象,而实用类只是方法的集合。
关注 熵减黑客 ,一起学习成长

分类:
设计模式
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端