单件模式:某一个类只有一个实例,并且这个实例是在类内部进行实例化,并向整个系统提供该实例。
单件模式UML类图:
class Program { static void Main(string[] args) { Singleton s1 = Singleton.GetSington(); Singleton s2 = Singleton.GetSington(); if (s1 == s2) { Console.WriteLine("相同"); } else { Console.WriteLine("不相同"); } Console.ReadKey(); } } public sealed class Singleton { private static Singleton _Singleton = null; private Singleton() { } public static Singleton GetSington() { if (_Singleton == null) { _Singleton = new Singleton(); } return _Singleton; } }
示例说明:
示例中使用Singleton类的GetSington()方法对单例进行处理,如果私有对象_Singleton为空则调用私有构造函数创建对象,如果私有对象不为空则返回直接返回_Singleton实例。
通过GetSington()方法保证获取对象实例时返回的是同一个实例,通过使用私有构造函数保证了对象不会被外部调用创建实例。
单件模式的另一种实现形式
public sealed class Singleton { public static readonly Singleton _Singleton = new Singleton(); private Singleton() { } }
这使得代码减少了许多,同时也解决了线程问题带来的性能上损失。那么它又是怎样工作的呢?
注意到,Singleton 类被声明为 sealed,以此保证它自己不会被继承,其次没有了 Instance 的方法,将原来_instance成员变量变成 public readonly,并在声明时被初始化。通过这些改 变,我们确实得到了 Singleton 的模式,原因是在 JIT 的处理过程中,如果类中的 static 属性 被任何方法使用时,.NET Framework 将对这个属性进行初始化,于是在初始化 Instance 属 性的同时 Singleton 类实例得以创建和装载。而私有的构造函数和readonly(只读)保证了 Singleton 不会被再次实例化,这正是 Singleton 设计模式的意图。 (摘自:http://www.cnblogs.com/huqingyu/archive/2004/07/09/22721.aspx)
不过这也带来了一些问题,比如无法继承,实例在程序一运行就被初始化,无法实现延迟初始化
多线程中单例模式
class Program { static void Main(string[] args) { Singleton s1 = Singleton.GetSington(); Singleton s2 = Singleton.GetSington(); if (s1 == s2) { Console.WriteLine("相同"); } else { Console.WriteLine("不相同"); } Console.ReadKey(); } } public sealed class Singleton { private static Singleton _Singleton = null; private static object obj = new object(); private Singleton() { } public static Singleton GetSington() { if (_Singleton == null) { lock (obj) { if (_Singleton == null) { _Singleton = new Singleton(); } } } return _Singleton; } }
Singleton模式优点:
1) 对唯一实例的受控访问, 因为Singleton类封装它的唯一实例,所以它可以严格的控制客户怎样以及何时访问它。
2) 缩小名空间,Singleton模式是对全局变量的一种改进。它避免了那些存储唯一实例的全局变量污染名空间。
3) 允许对操作和表示的精化Singleton类可以有子类,而且用这个扩展类的实例来配置一个应用是很容易的。你可以用你所需要的类的实例在运行时刻配置应用。
4) 允许可变数目的实例 这个模式使得你易于改变你的想法,并允许Singleton类的多个实例。此外,你可以用相同的方法来控制应用所使用的实例的数目。只有允许访问 Singleton实例的操作需要改变。