定义: 确保一个类只有一个实例, 并提供一个全局访问点。
原理: c# 中用 new 方法创建一个实例需要调用类的构造函数(注: 每一个类都必须有至少一个构造函数, 当我们未定义构造函数时,编译时编译器会帮我们生成一个公有的无参数的构造函数。), 当构造函数私有(private) 时,在类外部无法创建创建类的实例。
常用的几种实现方式:
1、只可在单线程下使用的实现
1 // 最简单的单线程下的单例模式 2 public class Singleton 3 { 4 // 局部静态变量记录 Singleton 类的唯一实例 5 private static Singleton uniqueInstance; 6 // 私有构造器,只有 Singleton 类内部才可调用构造器(创建实例) 7 private Singleton() { } 8 9 // 全局调用的静态方法 10 public static Singleton getInstance() 11 { 12 if (uniqueInstance == null) 13 { 14 uniqueInstance = new Singleton(); 15 } 16 17 return uniqueInstance; 18 } 19 }
2、饿汉模式
顾名思义, 一个人特别饿,一听到说有东西吃,马上将开始吃东西(加载类时就完成初始化)。
在加载时实例化,无需考虑多线程问题。优点是线程安全且不用锁,缺点是资源利用效率低。
1 // sealed : 使类无法被继承 2 public sealed class Singleton 3 { 4 // static 在静态初始化器(sttic initializ)中创建单间, 保证了线程安全 5 private static Singleton uniqueInstance = new Singleton(); 6 7 private Singleton() { } 8 // 提供全局接口 9 public static Singleton getInstance() 10 { 11 return uniqueInstance; 12 } 13 14 }
3、懒汉模式
同样顾名思义, 一个人特别懒,听到人喊吃饭(加载类),过来坐到饭桌前玩手机,非要等说开始吃饭才开吃(才实例化)。
延迟实例化, 需要通过 “双重检查加锁” 检查, 系统效率可以会低下。
1 // sealed : 使类无法被继承 2 public sealed class Singleton 3 { 4 // static 在静态初始化器(sttic initializ)中创建单间, 保证了线程安全 5 private static Singleton uniqueInstance = new Singleton(); 6 7 private Singleton() { } 8 9 public static Singleton getInstance() 10 { 11 return uniqueInstance; 12 } 13 14 } 15 16 // 不用 .net 提供的 Lazy 方法, 实现方法如下所示 17 public sealed class Singleton 18 { 19 private static Singleton uniqueInstance; 20 21 // 定一个标识,确保线程同步 22 private static readonly object locker = new object(); 23 24 private Singleton() { } 25 26 public static Singleton getInstacne() 27 { 28 if (uniqueInstance == null) 29 { 30 lock(locker) // 加锁, 第二个的线程在此处挂起 31 { 32 if (uniqueInstance == null) 33 { 34 uniqueInstance = new Singleton(); 35 } 36 } // 解锁, 第二个线程进入 37 } 38 39 return uniqueInstance; 40 }
以上是最近学习单例模式的总结, 如有不对,请指教!