你的位置:首页 > ASP.net教程

[ASP.net教程]设计模式实践之旅——Singleton Pattern


  在实际的项目中,经常需要对某些资源是唯一的并提供全局访问点。因为这些资源对象扮演者独一无二的角色,因此如何绕过常规的构造器,不让资源的调用者随意创建,这就需要一种机制来保证该资源对象只有一个 实例。单例模式的意图就是提供这种机制,保证一个类仅有一个实例,并提供一个访问它的全局访问点。  

  模型图

    逻辑模型图:

              

    物理模型图:

                                         

  实现实践

一、简单实现

public sealed class Singleton  {    static Singleton _instance ;    Singleton()    {    }    public static Singleton Instance    {      get      {        _instance = _instance ?? new Singleton();        return _instance;      }    }  }

  优势:

    1.实例是在 Instance 属性方法内部创建的,因此类可以使用附加功能(例如,对子类进行实例化)

    2.直到对象要求产生一个实例才执行实例化,避免了在应用程序启动时实例化不必要的 singleton

  劣势:

    1.这种方式的实现对于线程来说是不安全的,在多线程的环境下有可能得到Singleton类的多个实例。如果同时有两个线程去判断(_instance == null),并且得到的结果为真,这时两个线程都会创建类Singleton的实例,这样就违背了Singleton模式的意图

二、线程安全的实现

public sealed class Singleton  {    static Singleton _instance = null;    static readonly object Lock = new object();    Singleton()    {    }    public static Singleton Instance    {      get      {        lock (Lock)        {          _instance = _instance ?? new Singleton();          return _instance;        }      }    }  }

  优势:

    这种方式的实现对于线程来说是安全的。因为创建了一个进程辅助对象,线程在进入时会先对辅助对象加锁然后再检测对象是否被创建,这样可以确保只有一个实例被创建。这种情况下,对象实例由最先进入的那个线程创建,后来的线程在进入时(_instence == null)为假,不会再去创建对象实例了

  劣势:

    增加了额外的开销,损失了性能

三、双重锁定实现

public sealed class Singleton  {    static Singleton _instance = null;    static readonly object Lock = new object();    Singleton()    {    }    public static Singleton Instance    {      get      {        if (_instance == null)        {          lock (Lock)          {            if (_instance == null)            {              _instance = new Singleton();            }          }        }        return _instance;      }    }  }

  优势:

    1.解决了线程并发问题,同时避免在每个 Instance 属性方法的调用中都出现独占锁定。

    2.允许将实例化延迟到第一次访问对象时发生

  劣势:

    1.无法实现延迟初始化

四、静态初始化实现

public sealed class Singleton  {    private static readonly Singleton _instance;    static Singleton()    {      _instance = new Singleton();    }    Singleton()    {    }    public static Singleton Instance    {      get      {        return _instance;      }    }  }

  优势:   

    在此实现中,将在第一次引用类的任何成员时创建实例。该类标记为 sealed 以阻止发生派生,而派生可能会增加实例。此外,变量标记为 readonly,这意味着只能在静态初始化期间(此处显示的示例)或在类构造函数中分配变量。公共静态属性为访问实例提供了一个全局访问点。由于 Singleton 实例被私有静态成员变量引用,因此在类首次对Instance属性的调用所引用之前,不会发生实例化。在大多数情况下,静态初始化是在 .NET 中实现 Singleton 的首选方法。

  劣势:

    依赖公共语言运行库来初始化变量,对实例化机制的控制权比较少。在 Design Patterns 形式中,能够在实例化之前使用非默认的构造函数或执行其他任务。在此实现方案中由.NET Framework 负责执行初始化,因此没有这些选项

五、延迟初始化实现

public sealed class Singleton  {    Singleton()    {    }    public static Singleton Instance    {      get      {        return LazyLoad.instance;      }    }    class LazyLoad    {      static LazyLoad()      {      }      internal static readonly Singleton instance = new Singleton();    }  }

  优势:

      初始化工作有LazyLoad类的一个静态成员来完成,这样就实现了延迟初始化,是值得推荐的一种实现方式