C#单例模式
保证程序运行时只有一个实例,考点:静态构造函数、私有构造函数、锁、线程安全、延时创建对象、readonly/const区别
单例的优点:
1.保证了所有的对象访问的都是同一个实例
2.由于类是由自己类控制实例化的,所以有相应的伸缩性
单例的缺点:
1.额外的系统开销,因为每次使用类的实例的时候,都要检查实例是否存在,可以通过静态实例该解决。
2.无法销毁对象,单例模式的特性决定了只有他自己才能销毁对象实例,但是一般情况下我们都没做这个事情。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace SingletonPatterns 8 { 9 class Program 10 { 11 static void Main(string[] args) 12 { 13 } 14 } 15 16 #region 单例模式版本---1 17 /// <summary> 18 /// 该版本主要存在的问题(线程安全问题)当2个请求同时访问时可能会出现2个实例尽管不会异常 19 /// 不能保证运行过程中只有一个实例 20 /// </summary> 21 public sealed class Singleton1 22 { 23 private static Singleton1 _instance; 24 private Singleton1() { } 25 26 public static Singleton1 Instance 27 { 28 get 29 { 30 if (_instance == null) 31 _instance = new Singleton1(); 32 return _instance; 33 } 34 } 35 } 36 #endregion 37 38 #region 单例模式版本---2 39 /// <summary> 40 /// 使用在静态私有字段上通过new的形式,来保证在该类第一次被调用的时候创建实例,是不错的方式 41 /// 但有一点需要注意的是,C#其实并不保证实例创建的时机,因为C#规范只是在IL里标记该静态字段是BeforeFieldInit 42 /// 也就是说静态字段可能在第一次被使用的时候创建,也可能你没使用了,它也帮你创建了,也就是周期更早 43 /// 我们不能确定到底是什么创建的实例。 44 /// </summary> 45 public sealed class Singleton2 46 { 47 private static readonly Singleton2 _instance = new Singleton2(); 48 49 /// <summary> 50 /// 私有构造函数,确保用户在外部不能实例化新的实例 51 /// </summary> 52 private Singleton2() { } 53 54 public static Singleton2 Instance 55 { 56 get 57 { 58 return _instance; 59 } 60 } 61 } 62 #endregion 63 64 #region 单例模式版本---3 65 /// <summary> 66 /// 使用volatile来修饰,是个不错的注意,确保instance在被访问之前被赋值实例,一般情况都是用这种方式来实现单例。 67 /// </summary> 68 public sealed class Singleton3 69 { 70 private static volatile Singleton3 _instance = null; 71 72 /// <summary> 73 /// Lock对象 线程安全使用 74 /// </summary> 75 public static object syncObject = new object(); 76 77 private Singleton3() { } 78 79 public static Singleton3 Instance 80 { 81 get 82 { 83 if (_instance == null) 84 { 85 lock (syncObject) 86 { 87 if (_instance == null) 88 _instance = new Singleton3(); 89 } 90 } 91 return _instance; 92 } 93 } 94 } 95 #endregion 96 97 #region 单例模式版本---4 98 /// <summary> 99 /// 这种方式,其实是很不错的,因为他确实保证了是个延迟初始化的单例(通过加静态构造函数) 100 /// 但是该静态构造函数里没有东西哦,所以能有时候会引起误解,尤其是在code review或者代码优化的时候 101 /// 不熟悉的人可能直接帮你删除了这段代码,那就又回到了版本2了哦,所以还是需要注意的 102 /// 不过如果你在这个时机正好有代码需要执行的话,那也不错。 103 /// </summary> 104 public class Singleton4 105 { 106 /// <summary> 107 /// 因为下面声明了静态构造函数,所以在第一次访问该类之前,new Singleton()语句不会执行 108 /// </summary> 109 private static readonly Singleton4 _instance = new Singleton4(); 110 111 public static Singleton4 Instance 112 { 113 get { return _instance; } 114 } 115 116 private Singleton4() { } 117 118 /// <summary> 119 /// 声明静态构造函数就是为了删除IL里的BeforeFieldInit标记,以去静态自动在使用之前被初始化 120 /// </summary> 121 static Singleton4() { } 122 } 123 #endregion 124 125 #region 单例模式版本---5 126 127 #endregion 128 129 #region 单例模式版本---6 130 131 #endregion 132 133 134 }