C# 设计模式系列教程-单例模式

2019-12-30 12:47:00刘景俊

4. 代码实现:

  4.1 懒汉式


  public class Singleton
  {
    private static Singleton m_Instance;

    private Singleton()
    {
      // 将默认构造函数定义为私有,防止外部调用它实例化别的对象
    }

    public static Singleton GetInstance()
    {

      if (m_Instance == null)
      {
        m_Instance = new Singleton();
      }

      return m_Instance;
    }
  }

  4.2 饿汉式


  // 定义为sealed防止派生,因为派生可能增加实例
  public sealed class Singleton
  {
    private static readonly Singleton m_Instance = new Singleton();
    private Singleton()
    {
      // 将默认构造函数定义为私有,防止外部调用它实例化别的对象
    }

    public static Singleton GetInstance()
    {
      return m_Instance;
    }
  }

5. 模式总结

  5.1 优点:
    防止在应用程序中实例化多个对象。这就节约了开销,每个实例都要占用一定的内存,创建对象时需要时间和空间。

  5.2 缺点:

  5.3 适用场合:
    5.3.1 控制资源的使用,通过线程同步来控制资源的并发访问;
    5.3.2 控制实例产生的数量,达到节约资源的目的。
    5.3.3 作为通信媒介使用,也就是数据共享,它可以在不建立直接关联的条件下,让多个不相关的两个线程或者进程之间实现通信。

  5.4 对设计原则的支持:

    使用单例模式最核心的一点是体现了面向对象封装特性中的“单一职责”原则。

6. 补充: 在多线程开放过程中,对使用懒汉单例模式应防止两个线程同时去实例化对象,这是有可能的。

下面给出解决方案

  6.1 使用锁机制


  public class Singleton
  {
    private static Singleton m_Instance;

    static readonly object o = new object();

    private Singleton()
    {
      // 将默认构造函数定义为私有,防止外部调用它实例化别的对象
    }

    public static Singleton GetInstance()
    {
      lock (o)
      {
        if (m_Instance == null)
        {
          m_Instance = new Singleton();
        }
      }

      return m_Instance;
    }
  }

  使用锁机制可以防止两个线程同时创建对象,但这里有个性能问题,每当一个线程访问GetInstance()这个方法是,都要加锁,这其实是没必要的。