单例模式实现 (Singleton)
第一个版本:
1 // Bad code! Do not use! 2 public sealed class Singleton 3 { 4 private static Singleton instance=null; 5 6 private Singleton() 7 { 8 } 9 10 public static Singleton Instance 11 { 12 get 13 { 14 if (instance==null) 15 { 16 instance = new Singleton(); 17 } 18 return instance; 19 } 20 } 21 }
这个用例是线程不安全的,两个不同线程完全可能同时进入if (instance==null)并进行判断得出结果都为True,此时两个线程都将会去创建各自的实例对象,这就跟单例模式违反了。
第二个版本:
1 public sealed class Singleton 2 { 3 private static Singleton instance = null; 4 private static readonly object padlock = new object(); 5 6 Singleton() 7 { 8 } 9 10 public static Singleton Instance 11 { 12 get 13 { 14 lock (padlock) 15 { 16 if (instance == null) 17 { 18 instance = new Singleton(); 19 } 20 return instance; 21 } 22 } 23 } 24 }
第二个版本成功解决了第一个版本中存在的线程不安全的问题---加入了锁机制。但问题也随之而来,加入锁机制后,每次要获取instance都会先判断是否被锁,在这里,都讲成为单管道,效率明显减低。
第三个版本:
1 // Bad code! Do not use! 2 public sealed class Singleton 3 { 4 private static Singleton instance = null; 5 private static readonly object padlock = new object(); 6 7 Singleton() 8 { 9 } 10 11 public static Singleton Instance 12 { 13 get 14 { 15 if (instance == null) 16 { 17 lock (padlock) 18 { 19 if (instance == null) 20 { 21 instance = new Singleton(); 22 } 23 } 24 } 25 return instance; 26 } 27 } 28 }
为了解决第二个版本中的效率问题,在第三个版本中修改了锁机制,但这样真的就解决问题了吗?还真没有。具体见http://csharpindepth.com/Articles/General/Singleton.aspx#dcl
第四个版本:
1 public sealed class Singleton 2 { 3 private static readonly Singleton instance = new Singleton(); 4 5 // Explicit static constructor to tell C# compiler 6 // not to mark type as beforefieldinit 7 static Singleton() 8 { 9 } 10 11 private Singleton() 12 { 13 } 14 15 public static Singleton Instance 16 { 17 get 18 { 19 return instance; 20 } 21 } 22 }
第四版本很好的取消掉了锁机制带来的问题,但还是没有解决懒惰加载的问题。
第五个版本:
public sealed class Singleton { private Singleton() { } public static Singleton Instance { get { return Nested.instance; } } private class Nested { // Explicit static constructor to tell C# compiler // not to mark type as beforefieldinit static Nested() { } internal static readonly Singleton instance = new Singleton(); } }
更好的第六个版本:(使用4.0+)
1 public sealed class Singleton 2 { 3 private static readonly Lazy<Singleton> lazy = 4 new Lazy<Singleton>(() => new Singleton()); 5 6 public static Singleton Instance { get { return lazy.Value; } } 7 8 private Singleton() 9 { 10 } 11 }
扩展的第七个版本:
1 /// <summary> 2 /// A base class for the singleton design pattern. 3 /// </summary> 4 /// <typeparam name="T">Class type of the singleton</typeparam> 5 public abstract class SingletonBase<T> where T : class 6 { 7 #region Members 8 9 /// <summary> 10 /// Static instance. Needs to use lambda expression to construct an instance (since constructor is private). 11 /// </summary> 12 private static readonly Lazy<T> sInstance = new Lazy<T>(() => CreateInstanceOfT()); 13 14 #endregion 15 16 #region Properties 17 18 /// <summary> 19 /// Gets the instance of this singleton. 20 /// </summary> 21 public static T Instance { get { return sInstance.Value; } } 22 23 #endregion 24 25 #region Methods 26 27 /// <summary> 28 /// Creates an instance of T via reflection since T's constructor is expected to be private. 29 /// </summary> 30 /// <returns></returns> 31 private static T CreateInstanceOfT() 32 { 33 try 34 { 35 return Activator.CreateInstance(typeof(T), true) as T; 36 } 37 catch (MissingMethodException ex) 38 { 39 throw new TypeLoadException( 40 string.Format( 41 System.Globalization.CultureInfo.CurrentCulture, 42 "The type '{0}' must have a private constructor to be used in the Singleton pattern.", 43 typeof(T).FullName), 44 ex); 45 }//end try/catch 46 } 47 48 #endregion 49 }
参考:
http://csharpindepth.com/Articles/General/Singleton.aspx
http://www.codeproject.com/Articles/572263/A-Reusable-Base-Class-for-the-Singleton-Pattern-in