英文: Singleton Pattern
单例模式确保的是对于整个系统而言,一个类的实例只会存在一个。单例模式通常分为懒汉和饿汉两种。

  • 懒汉:类实例在第一次调用的时候才会去产生
  • 饿汉:类实例早已存在,取的时候直接返回

    1.1、懒汉方式

    既然是单例模式,就是类实例是不能让外部直接new创建的,那么对于构造函数的私有化是必要的。 而且上面说过懒汉方式时在第一次调用的时候来创建类的实例,那么必须考虑并发,通常情况下对并发的控制是通过加锁来实现的:
    1. public class Singleton_Idler
    2. {
    3. private static volatile Singleton_Idler singleton_Idler = null;
    4. private static readonly object lock_obj = new object();
    5. // 构造函数私有化
    6. private Singleton_Idler() { }
    7. // 提供方法供外部调用产生实例,使用双判断加锁
    8. public Singleton_Idler CreateInstance() {
    9. if (singleton_Idler == null) {
    10. lock (lock_obj) {
    11. if (singleton_Idler == null) {
    12. singleton_Idler = new Singleton_Idler();
    13. }
    14. }
    15. }
    16. return singleton_Idler;
    17. }
    18. }

    1.2、饿汉方式1

    public class Singleton2
    {
      // 直接先实例化
      // 缺点就是在程序初始化后, 静态对象就被CLR构造了, 哪怕你没用
      private static readonly Singleton2 instance = new Singleton2();
      private Singleton2() { }
      public Singleton2 GetInstance => instance;
    }
    

    1.3、饿汉方式2

    public class Singleton3
    {
      private static Singleton3 instance = null;
      private Singleton3() { }
      // 通过静态构造函数实例化
      // 静态构造函数在第一次使用该类之前被运行时调用,只会执行一次,外部不能访问
      static Singleton3()
      {
          instance = new Singleton3();
      }
      public Singleton3 GetInstance => instance;
    }
    

    1.4、总结

    单例模式一般使用在要求一个类有且仅有一个对象的场景下, 比如EF的上下文对象,数据库的连接池对象等等。 如果项目中使用的依赖注入容器,比如Autofac,那么对于单例模式怎么实现我们是不必要如此关心的,直接使用提供的方法注入然后获取即可。