记一下学习单例模式的笔记: 单例就是要保证该类仅有一个实例。实现完全封闭的单例(外部不能new)其实就要两点要求:
根据new实例的时机,分为饿汉式和懒汉式: 一、 饿汉式单例:静态变量初始化时new 特点:加载时new,一开始全局就存在该唯一实例,每次用到只要获取就行,提前占用系统资源但不存在线程安全问题。代码如下: 1 public sealed class Singleton 2 { 3 private static readonly Singleton instance = new Singleton(); 4 private Singleton() { } 5 6 public static Singleton GetInstance() 7 { 8 return instance; 9 } 10 } 二、 懒汉式单例:需要该实例的时候再new 特点:真正需要用到的时候才实例化,不提前占用资源但多个线程同时用到该实例时,会存在判断静态变量都为null都去new而产生多个实例的情况。有线程安全问题,但可以用双重锁定解决。 单线程懒汉单例代码如下: 1 public class Singleton 2 { 3 private static Singleton instance = null; 4 private Singleton() { } 5 6 public static Singleton GetInstance() 7 { 8 if (instance == null) 9 instance = new Singleton(); 10 return instance; 11 } 12 } 多线程懒汉单例代码如下: 1 public class Singleton 2 { 3 private static Singleton instance = null; 4 private static readonly object obj = new object(); 5 private Singleton() { } 6 7 public static Singleton GetInstance() 8 { 9 //双重锁定 10 if (instance == null)//只有为null需要实例化处理时才进行加锁,提高性能避免不必要的等待 11 { 12 lock (obj) 13 { 14 if (instance == null)//避免其他线程等待锁释放期间有线程已经实例化,从而造成多个实例 15 instance = new Singleton(); 16 } 17 } 18 return instance; 19 } 20 } 三、 注册式单例 介绍一个有意思的单例-泛型注册式,是对单例的扩展,主要了解它的设计思想。 其实每个类单例模式实现代码都是差不多的:
实现代码如下(例子使用饿汉式,当然也可以用懒汉式): 1 public abstract class Singleton<T> where T:class,new() 2 { 3 private static readonly T instance = new T(); 4 protected Singleton() { } 5 6 public static T GetSingleton()//获取单例 7 { 8 return instance; 9 } 10 } 11 public class Person : Singleton<Person> { } 可以看到这种单例通过继承的方式,既可以new实例也可以获取单例实例。如果要实现上面的完全封闭(禁用外部new),也可以完全在Person类中写个私有构造器在Singleton<T>类中实例的获取new T()改为反射调用私有构造器的方式实现,总感觉怪怪的。 下面是主程序调用该单例方法: 1 static void Main(string[] args) 2 { 3 Person p1 = Person.GetSingleton(); 4 Person p2 = Singleton<Person>.GetSingleton(); 5 6 if (object.ReferenceEquals(p1, p2)) 7 { 8 Console.WriteLine("两个对象是同一实例"); 9 } 10 Console.ReadKey(); 11 } 12 输出结果:
|
|