单列模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。(全局访问和实例化控制)
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Singleton { class Singleton { private static Singleton instance; private Singleton() { //使用private修饰构造函数,这样外面调用的时候就没有办法使用new来实例化对象了。 } public static Singleton GetInstance()//此方法是获得本类实例的唯一全局访问点 { if (instance == null)//若不存在,则实例化一个对象,否则返回已有实例。 { instance = new Singleton(); } return instance; } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Singleton { class Program { static void Main(string[] args) { Singleton s1 = Singleton.GetInstance(); Singleton s2 = Singleton.GetInstance(); if(s1==s2){ Console.Write("两个对象是相同的实例"); } Console.Read(); } } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Singleton { class Singleton { private static Singleton instance; private static readonly object syncRoot = new object();//程序运行时创建一个静态只读的进程辅助对象。 private Singleton() { } public static Singleton GetInstance() { if (instance == null)//先判断实例是否存在,若不存在则做枷锁处理。 { lock (syncRoot) { if (instance == null)//若不存在,则实例化一个对象,否则返回已有实例。 { instance = new Singleton(); } } } return instance; } } } //两处对instance进行判断: //当instance为null并且同时有两个线程调用GetInstance()的时候,它们将都可以通过第一重instance==null的判断。 //然后由于lock的机制,这两个线程只有一个进入,另一个在外面排队等候,必须要其中一个进入并且出来之后,另一个才能进入。 //而此时若没有第二处的判断,则第一个线程创建了实例,而第二个线程还可以继续创建一个新的实例,这就失去了单列的目的!
在C#中,在多线程下的单列可分为:懒汉式单列和饿汉式单例。上面那个是懒汉式的。
下面这个是饿汉式单例,在类被调用的时候,就已经创建出类的实例。
利用sealed(密封类)和readonly 关键字
public sealed class Singleton{ private static readonly Singleton instance=new Singleton();//在第一次引用类的任何成员时创建实例,公共语言运行库负责处理变量初始化 private Singleton(){} public static Singleton GetInstance(){return instance} }
单列模式是为了只存在一个实例,适用于数据库连接池、线程池、IOC容器实例。
单列模式会长期持有一个对象,不会释放,所以并不是所有地方都适合单列。