赞
踩
本文是个人基于C#学习设计模式总结的学习笔记,希望对你有用!
定义:确保一个类只有一个实例,并提供一个全局访问点。
本质就是保证在整个应用程序的生命周期中,任何一个时刻,单例类的实例都只存在一个。
单例模式通常适用于在整个应用程序中只需要一个实例化对象的场景,以确保资源的高效利用和应用程序的稳定性。
- 懒汉式:类加载不会导致该单实例对象被创建,而是首次使用该对象时才会创建。
- 饿汉式:类加载就会导致该单实例对象被创建。
/// <summary> /// 单例模式的实现 /// </summary> public class Singleton { //定义一个静态变量用于保存实例 private static Singleton instance; private Singleton() { //将构造函数私有化,使外界不能创建该类实例 } //定义公有静态方法,提供一个全局访问点(也可以定义公有属性作为全局访问点) public static Singleton GetInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
在GetInstance方法中,我们检查instance是否为null,如果是,则创建一个新的Singleton实例并将其赋值给instance。最后,我们返回instance实例。这样,无论何时调用Instance属性,它都将返回同一个Singleton实例。通过这种方式,我们实现了单例模式,确保了整个应用程序中只有一个Singleton实例存在,并提供了一个全局访问点来访问该实例。
/// <summary> /// 单例模式的实现 /// </summary> public class Singleton { //定义一个静态变量用于保存实例 private static Singleton _instance; //定义公有静态属性,提供一个全局访问点 public static Singleton Instance { get { if (_instance == null) { _instance = new Singleton(); } return _instance; } set { _instance = value; } } private Singleton() { //将构造函数私有化,使外界不能创建该类实例 } }
此种方法同上面的方法是一样的作用,只不过调用的时候,一个是使用方法,一个是使用属性而已。
以上的代码实现了在单线程下是OK的,然而在多线程的情况下会得到多个Singleton 实例,因为在两个线程同时运行GetInstance方法时,此时两个线程判断(_instance ==null)
这个条件时都返回真,此时两个线程就都会创建Singleton的实例,这样就违背了我们单例模式初衷了,既然上面的实现会运行多个线程执行,那我们对于多线程的解决方案自然就是使GetInstance方法在同一时间只运行一个线程运行就好了
/// <summary> /// 单例模式的实现 /// </summary> public class Singleton { //定义一个静态变量用于保存实例 private static Singleton _instance; //定义一个线程锁 private static readonly object _instanceLock = new object(); //定义公有静态属性,提供一个全局访问点 public static Singleton Instance { get { lock (_instanceLock) { if (_instance == null) { _instance = new Singleton(); } } return _instance; } set { _instance = value; } } private Singleton() { //将构造函数私有化,使外界不能创建该类实例 } }
上面这种解决方案确实可以解决多线程的问题,但是上面代码对于每个线程都会对线程辅助对象locker加锁之后再判断实例是否存在,对于这个操作完全没有必要的,因为当第一个线程创建了该类的实例之后,后面的线程此时只需要直接判断(_instance==null)
为假,此时完全没必要对线程辅助对象加锁之后再去判断,所以上面的实现方式增加了额外的开销,损失了性能,为了改进上面实现方式的缺陷,我们只需要在lock语句前面加一句(_instance==null)
的判断就可以避免锁所增加的额外开销,这种实现方式我们就叫它 “双重锁定”
/// <summary> /// 单例模式的实现 /// </summary> public class Singleton { //定义一个静态变量用于保存实例 private static Singleton _instance; //定义一个线程锁 private static readonly object _instanceLock = new object(); //定义公有静态属性,提供一个全局访问点 public static Singleton Instance { get { if (_instance==null) { lock (_instanceLock) { if (_instance == null) { _instance = new Singleton(); } } } return _instance; } set { _instance = value; } } private Singleton() { //将构造函数私有化,使外界不能创建该类实例 } }
/// <summary> /// 单例模式的实现 /// </summary> public class Singleton { //定义一个私有静态的只读的全局变量 private static readonly Singleton instance = new Singleton(); private Singleton() { //将构造函数私有化,使外界不能创建该类实例 } //设置为静态方法则可在外边无需创建该类的实例就可调用该方法 public static Singleton GetInstance() { return instance; } }
在c#中使用静态初始化时无需显示地编写线程安全代码,C# 与 CLR 会自动解决前面提到的懒汉式单例类时出现的多线程同步问题。
当整个类被加载的时候,就会自行初始化 instance 这个静态只读变量。
而非在第一次调用 GetInstance()时再来实例化单例类的唯一实例,所以这就是一种饿汉式的单例类
以上就是今天要讲的内容,本文介绍了单例模式的使用,而希望以上内容可以帮助到大家,如文中有不对之处,还请批评指正。
参考资料
C#设计模式(1)——单例模式
C#中单例模式详解
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。