在软件开发中,单例模式是一种常见的设计模式,它确保一个类只有一个实例,并提供一个全局访问点。然而,每次实现单例模式都涉及到重复的代码,这不仅增加了工作量,也降低了代码的可读性和可维护性。为了解决这个问题,创建了一个可重用的单例基类,可以在所有项目中使用。今天,想与大家分享成果。
这个基类的目的是在创建新的单例时将编码工作量降到最低。这不仅意味着可以减少手指疲劳的编码工作,而且还可以使创建的单例更加易于阅读和维护。此外,这个基类还支持线程安全,这对于单例来说是非常重要的。
今天要展示的代码包含两个类:
就是这样。非常简单,对吧?现在让深入探讨!
将先展示一个非常简单的单例类,它从神奇单例基类派生(稍后将展示)。
public class SingletonExample : SingletonBase<SingletonExample>
{
public string SomeString { get; set; }
private SingletonExample() { }
}
从上面的示例中,可以学到三个重要的点:
如所见,单例本身非常简单。所有的重活都由基类完成。所以可以专注于实现一直梦寐以求的那些花哨的方法和属性。
现在让看看好东西:神奇单例基类!在这里,想要确保单例只有一个实例存在。希望以线程安全的方式做到这一点。让一步一步来:
public abstract class SingletonBase<T> where T : class
{
private static readonly Lazy<T> sInstance = new Lazy<T>(() => CreateInstanceOfT());
public static T Instance { get { return sInstance.Value; } }
private static T CreateInstanceOfT()
{
return Activator.CreateInstance(typeof(T), true) as T;
}
}
首先,声明单例基类。如所见,这是一个模板类(这就是“T”先生的来源)。这允许传递单例的类作为类型参数(参见上面的示例)。
接下来,需要回答一个重要的问题:用户如何访问单例的实例?这个问题通常通过提供一个名为“Instance”的属性来解决(非常有创意,对吧?)。这个属性返回单例的唯一实例。下面是如何实现它的:
private static readonly Lazy<T> sInstance = new Lazy<T>(() => CreateInstanceOfT());
public static T Instance { get { return sInstance.Value; } }
首先,有一个名为“sInstance”的静态成员。它持有单例实例,并且是延迟初始化的。这是通过使用.NET 4.0的Lazy<T>类轻松实现的。最好的事情是:Lazy<T>是完全线程安全的!
第二件要注意的事情是神秘的方法“CreateInstanceOfT”。为什么需要它?为什么不直接调用new?这是因为单例有一个私有构造函数(如果忘记了,只需向上滚动一点到SingletonExample类)。由于这个原因,不得不使用一个小把戏:激活器(Activator)!
有了这个小方法的帮助,现在可以实例化单例类,尽管它的构造函数是私有的。很酷,对吧?
就是这样!现在已经看到了整个单例基类。下面是所有这些部分组合在一起的完整类,准备好复制和粘贴:
public abstract class SingletonBase<T> where T : class
{
private static readonly Lazy<T> sInstance = new Lazy<T>(() => CreateInstanceOfT());
public static T Instance { get { return sInstance.Value; } }
private static T CreateInstanceOfT()
{
return Activator.CreateInstance(typeof(T), true) as T;
}
}