设计模式:单例模式(至少有一种你没有见过)
背景
本文中的例子多是从《clr via c#》中抄袭而来,读过这本书最后一章的朋友,应该见过各种实现了。
各种实现
第一种:简单版本
代码
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace DesignPatternStudy.Creations.Singletons 8 { 9 class SimpleSingleton 10 { 11 private static readonly SimpleSingleton _instance; 12 13 private SimpleSingleton() { } 14 15 static SimpleSingleton() 16 { 17 _instance = new SimpleSingleton(); 18 } 19 20 public static SimpleSingleton Singleton 21 { 22 get 23 { 24 return _instance; 25 } 26 } 27 } 28 }
说明:静态构造方法是线程安全的,因此可以保证单例。如果单例类型有其它静态方法,调用这些方法会导致单例被初始化。
第二种:嵌套类
代码
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace DesignPatternStudy.Creations.Singletons 8 { 9 class NestedSingleton 10 { 11 private NestedSingleton() { } 12 13 public static NestedSingleton Singleton 14 { 15 get 16 { 17 return Nested._instance; 18 } 19 } 20 21 public static void OtherStaticMethod() 22 { 23 Console.WriteLine("不会产生单例!"); 24 } 25 26 private class Nested 27 { 28 public static readonly NestedSingleton _instance; 29 30 static Nested() 31 { 32 _instance = new NestedSingleton(); 33 } 34 } 35 } 36 }
说明:解决了“简单版本”的问题,调用单例类型的静态方法不会导致单例被实例化。
第三种:双校验+悲观锁
代码
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace DesignPatternStudy.Creations.Singletons 8 { 9 class DoubleCheckSingleton 10 { 11 private static readonly Object _lock = new Object(); 12 private static DoubleCheckSingleton _instance; 13 14 private DoubleCheckSingleton() { } 15 16 public static DoubleCheckSingleton Singleton 17 { 18 get 19 { 20 if (_instance != null) 21 { 22 return _instance; 23 } 24 25 lock (_lock) 26 { 27 if (_instance == null) 28 { 29 _instance = new DoubleCheckSingleton(); 30 } 31 } 32 33 return _instance; 34 } 35 } 36 } 37 }
说明:设计模式的作者使用的语言是 C++,C++ 没有和 C# 静态构造方法同样语义的机制,因此使用了这种双校验机制。
第四种:双校验+乐观锁
代码
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using System.Threading; 7 8 namespace DesignPatternStudy.Creations.Singletons 9 { 10 class CASSingleton 11 { 12 private static CASSingleton _instance; 13 14 private CASSingleton() 15 { 16 Console.WriteLine("CASSingleton"); 17 } 18 19 public static CASSingleton Singleton 20 { 21 get 22 { 23 if (_instance != null) 24 { 25 return _instance; 26 } 27 28 Interlocked.CompareExchange(ref _instance, new CASSingleton(), null); // 相当于:update xxx_table set version = new_version where version = old_version 29 30 return _instance; 31 } 32 } 33 } 34 }
说明:乐观锁在某些情况下是比悲观锁好用,在本例中有一点要求:构造方法的执行必须没有副作用,因为内部可能创建多个实例,外部只会看到一个。
备注
看完大师的书籍,觉得自己好渺小,继续努力吧。