索引:
一、说明
本文中的代码类,在生产中使用了很长的时间,曾应用于多个企业多个项目实践中,其中也踩了不少坑,总结了一些适用的业务情景,
重要的事情说三遍:
a.本代码类不是万能药,不要在业务情景中滥用!
b.本代码类是有效的可用的经典的,但不要在业务情景中滥用!!
c.本代码类是经过实践考验的,可放心使用,但不要在业务情景中滥用!!!
具体滥用后会踩中什么坑呢?嘿嘿~~认真看下面代码结合自己业务应用,自己分析问题~~
二、代码
废话不多说,代码如下:
1 /// <summary> 2 /// 惰性泛型单例 3 /// </summary> 4 public class LazyInstance<T> 5 where T : class,new() 6 { 7 private static Lazy<T> lazyObj = new Lazy<T>(() => new T()); 8 9 public static T Instance 10 { 11 get 12 { 13 return lazyObj.Value; 14 } 15 } 16 }
三、.NET 内置类及代码说明
查看MSDN文档,Lazy<T> 类,https://msdn.microsoft.com/zh-cn/library/dd642331(v=vs.110).aspx :
1 // 2 // 摘要: 3 // 提供对延迟初始化的支持。 4 // 5 // 类型参数: 6 // T: 7 // 指定正在延迟初始化的对象的类型。 8 public class Lazy<T> 9 { }
1 // 2 // 摘要: 3 // 初始化 System.Lazy`1 类的新实例。发生延迟初始化时,使用指定的初始化函数。 4 // 5 // 参数: 6 // valueFactory: 7 // 在需要时被调用以产生延迟初始化值的委托。 8 // 9 // 异常: 10 // T:System.ArgumentNullException: 11 // valueFactory 为 null。 12 public Lazy(Func<T> valueFactory);
1 // 2 // 摘要: 3 // 获取当前 System.Lazy`1 实例的延迟初始化值。 4 // 5 // 返回结果: 6 // 当前 System.Lazy`1 实例的延迟初始化值。 7 // 8 // 异常: 9 // T:System.MemberAccessException: 10 // System.Lazy`1 实例初始化为使用正在惰性初始化的类型的默认构造函数,并且缺少访问该构造函数的权限。 11 // 12 // T:System.MissingMemberException: 13 // System.Lazy`1 实例初始化为使用正在惰性初始化的类型的默认构造函数,并且该类型没有无参数的公共构造函数。 14 // 15 // T:System.InvalidOperationException: 16 // 初始化函数尝试访问此实例上的 System.Lazy`1.Value。 17 [DebuggerBrowsable(DebuggerBrowsableState.Never)] 18 public T Value { get; }
Lazy<T> 类,我们说完了,若果还不明白就自己搜索一下,接下来说一下使用此类怎么构成了单例:
初始化时:
1 private static Lazy<T> lazyObj = new Lazy<T>(() => new T());
在使用某个实例类时,例如 class A ,总是使用 A.Instance,而该属性总是返回Lazy<T>.Value:
1 public static T Instance 2 { 3 get 4 { 5 return lazyObj.Value; 6 } 7 }
注意,上面都是用static修饰的,典型的构造函数赋值静态属性,实例使用静态属性保存值,只不过巧妙的借用了.NET内置的Lazy<T> 类,
完成实现了经典的单例模式,同时省去了锁,惰性等实现代码,同时代码超级稳定!
四、使用方式
定义一个类:
1 public class ClassA : LazyInstance<ClassA> 2 { 3 public string Test() 4 { 5 return "惰性泛型单例!"; 6 } 7 }
在方法中使用这个类:
1 public void Invoke() 2 { 3 var result = ClassA.Instance.Test(); 4 }
蒙
2016-09-30 23:11 周五