单例子模式定义
保证一个类仅有一个实例,并提供一个访问它的全局访问点.
通常我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象。一个最好的办法就是让类自身负责保存它的唯一实例。这个类可以保证没有其它实例可以呗创建并且它可以提供一个访问该实例的方法,这就是单例模式。
单例子模式简单实现
Singleton类定义了一个GetInstance 操作,允许客户访问它的唯一实例,GetInstance是一个静态方法,主要负责创建自己的唯一实例。
public class Singleton { private static Singleton _instance; private Singleton()//私有化构造函数,阻止外界利用new关键词来创建实例 {} public static Singleton GetInstance() { return _instance ?? (_instance = new Singleton()); } }
测试代码
public void Myaction() { var s1 = Singleton.GetInstance(); var s2 = Singleton.GetInstance(); if (s1 == s2) { Console.WriteLine("两个对象是相同的!"); } Console.Read(); }
多线程时的单例
上面的代码在多线程的程序下运行明细是有问题的,当多个线程同时访问Singleton类 都调用GetInstance()方法,就有可能会创建多个实例。
这种情况我们可以给进程一把锁来处理,这里需要理解 lock 语句的涵义,lock 是确保当前一个线程位于代码的临界区时,另一个线程不进入临界区。如果其它线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放。
简单实现
public class Singleton { private static Singleton _instance; //程序执行时创建一个静态的只读的进程辅助对象 private static readonly object SyncRoot = new object(); private Singleton()//私有化构造函数,阻止外界利用new关键词来创建实例 { } public static Singleton GetInstance() { lock (SyncRoot)//在同一时刻加了锁的那部分程序只有一个线程可以进入 { _instance= _instance ?? (_instance = new Singleton()); } return _instance; } }
双重锁定(Double-Check Locking)
通过上面的例子我们不难发现当我们每次调用 GetInstance() 方法时都要 lock 这种做法显然是影响性能的所以我们需要再加一层判断
简单实现
public class Singleton { private static Singleton _instance; //程序执行时创建一个静态的只读的进程辅助对象 private static readonly object SyncRoot = new object(); private Singleton()//私有化构造函数,阻止外界利用new关键词来创建实例 {} public static Singleton GetInstance() { if (_instance == null)//先判断实例是否存在,不存在在枷锁处理 { lock (SyncRoot)//在同一时刻加了锁的那部分程序只有一个线程可以进入 { _instance = _instance ?? (_instance = new Singleton()); } } return _instance; } }
工厂单例创建数据上下文
我们在开发过程中经常都需要对数据上下文进行单例,所以这里结合简单工厂 来实现数据上下文的创建
简单实现
public class DbFactory { private static readonly object SyncRoot=new object(); private DbFactory() {} #region 获取当前的上下文对象 /// <summary> /// 单例工厂 获取当前的上下文对象 //考虑多线程情况 /// </summary> /// <returns></returns> public static SiyoukuContext GetCurrentDbContext() { var context = (SiyoukuContext) CallContext.GetData("DbContext"); //从数据槽获取 if (context == null) { lock (SyncRoot)//双重锁定 { if (context == null) { //如果不存在 ,则实例化一个上下文对象 context = new SiyoukuContext(); CallContext.SetData("DbContext", context); } } } return context; } #endregion }
本文记录了自己对单例模式的总结
本文永久更细地址:http://siyouku.cn/article/6812.html