C#实现单例模式的几种方法
单例模式,也叫单子模式,是一种常用的软件设计模式,属于创建型模式的一种。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息。这种方式简化了在复杂环境下的配置管理。
单例模式在设计模式中可以说非常的典型,在面试中也是最多被问起的,以下是C#实现单例模式的几种方法:
第一种
 public sealed class Singleton1
    {
        private static Singleton1 _singleton1;
        private Singleton1()
        {
	      Console.WriteLine("实例化一次!");
        }
        public Singleton1 CreateInstance()
        {
              return _singleton1 ??= new Singleton1();
        }
    }
 
单线程:
    class Program
    {
        static void Main(string[] args)
        {
            for (int i = 0; i < 5; i++)
            {
                Singleton1.CreateInstance();
            }
            Console.ReadKey();
        }
    }
 
结果:
多线程:
 class Program
    {
        static void Main(string[] args)
        {
// for (int i = 0; i < 5; i++)
// {
// Singleton1.CreateInstance();
// }
            for (int i = 0; i < 5; i++)
            {
                Task.Run(Singleton1.CreateInstance);
            }
            Console.ReadKey();
        }
    }
 
结果:
最简单的单例模式,但不适用于多线程
第二种
 public sealed class Singleton2
    {
        private static Singleton2 _singleton2;
        private static readonly object Singleton2Lock = new object();
        private Singleton2()
        {
	      Console.WriteLine("实例化一次!");
        }
        public static Singleton2 CreateInstance()
        {
            lock (Singleton2Lock)
            {
                 return _singleton2 ??= new Singleton2();
            }
          
        }
    }
 
直接上结果:
加了线程锁,多线程运行也没问题,但效率不高
第三种
 public sealed class Singleton3
    {
        private static Singleton3 _singleton3;
        private static readonly object Singleton3Lock =  new object();
        private Singleton3()
        {
  	    Console.WriteLine("实例化一次!");
        }
        public Singleton3 CreateInstance()
        {
            if (_singleton3==null)
            {
                lock (Singleton3Lock)
                {
                     return _singleton3 ??= new Singleton3();
                }
            }
            return _singleton3;
        }
    }
 
在lock前再加入if判断,减少后续线程不必要的等待,比较经典《双if+lock》的写法
第四种(推荐)
 public sealed class Singleton4
    {
        private static  readonly Singleton4 _singleton4=new Singleton4();
        static Singleton4()
        {
	    Console.WriteLine("实例化一次!");
        }
        public static Singleton4 CreateInstance()
        {
            return _singleton4;
        }
    }
 
我们知道C#会在调用静态构造函数时初始化静态变量,并且CLR会保证静态构造函数只被调用一次,这样我们就能保证Singleton4只被实例化一次。运用CLR特性,并且代码足够简洁。
第五种(推荐)
 public sealed class Singleton5
    {
        public static Singleton5 CreateInstance()
        {
            return Nested.Singleton5;
        }
    }
    public class Nested
    {
        internal static readonly Singleton5 Singleton5 = new Singleton5();
        static Nested()
        {
	    Console.WriteLine("实例化一次!");
        }
    }
 
和第四种方法很像,不过这样可以做到按需创建,只要我们不调用Singleton5.CreateInstance,Singleton5的实例就不会被创建。
