模型图
逻辑模型图:
物理模型图:
实现实践
一、简单实现
public sealed class Singleton { static Singleton _instance ; Singleton() { } public static Singleton Instance { get { _instance = _instance ?? new Singleton(); return _instance; } } }
优势:
1.实例是在 Instance 属性方法内部创建的,因此类可以使用附加功能(例如,对子类进行实例化)
2.直到对象要求产生一个实例才执行实例化,避免了在应用程序启动时实例化不必要的 singleton。
劣势:
1.这种方式的实现对于线程来说是不安全的,在多线程的环境下有可能得到Singleton类的多个实例。如果同时有两个线程去判断(_instance == null),并且得到的结果为真,这时两个线程都会创建类Singleton的实例,这样就违背了Singleton模式的意图
二、线程安全的实现
public sealed class Singleton { static Singleton _instance = null; static readonly object Lock = new object(); Singleton() { } public static Singleton Instance { get { lock (Lock) { _instance = _instance ?? new Singleton(); return _instance; } } } }
优势:
这种方式的实现对于线程来说是安全的。因为创建了一个进程辅助对象,线程在进入时会先对辅助对象加锁然后再检测对象是否被创建,这样可以确保只有一个实例被创建。这种情况下,对象实例由最先进入的那个线程创建,后来的线程在进入时(_instence == null)为假,不会再去创建对象实例了
劣势:
增加了额外的开销,损失了性能
三、双重锁定实现
public sealed class Singleton { static Singleton _instance = null; static readonly object Lock = new object(); Singleton() { } public static Singleton Instance { get { if (_instance == null) { lock (Lock) { if (_instance == null) { _instance = new Singleton(); } } } return _instance; } } }
优势:
1.解决了线程并发问题,同时避免在每个 Instance 属性方法的调用中都出现独占锁定。
2.允许将实例化延迟到第一次访问对象时发生
劣势:
1.无法实现延迟初始化
四、静态初始化实现
public sealed class Singleton { private static readonly Singleton _instance; static Singleton() { _instance = new Singleton(); } Singleton() { } public static Singleton Instance { get { return _instance; } } }
优势:
在此实现中,将在第一次引用类的任何成员时创建实例。该类标记为 sealed 以阻止发生派生,而派生可能会增加实例。此外,变量标记为 readonly,这意味着只能在静态初始化期间(此处显示的示例)或在类构造函数中分配变量。公共静态属性为访问实例提供了一个全局访问点。由于 Singleton 实例被私有静态成员变量引用,因此在类首次对Instance属性的调用所引用之前,不会发生实例化。在大多数情况下,静态初始化是在 .NET 中实现 Singleton 的首选方法。
劣势:
依赖公共语言运行库来初始化变量,对实例化机制的控制权比较少。在 Design Patterns 形式中,能够在实例化之前使用非默认的构造函数或执行其他任务。在此实现方案中由.NET Framework 负责执行初始化,因此没有这些选项
五、延迟初始化实现
public sealed class Singleton { Singleton() { } public static Singleton Instance { get { return LazyLoad.instance; } } class LazyLoad { static LazyLoad() { } internal static readonly Singleton instance = new Singleton(); } }
优势:
初始化工作有LazyLoad类的一个静态成员来完成,这样就实现了延迟初始化,是值得推荐的一种实现方式