设计模式实践之旅——Singleton Pattern

来源:互联网 发布:js注释快捷键 edit 编辑:程序博客网 时间:2024/06/15 07:54
在实际的项目中,经常需要保证某些资源是唯一的并提供全局访问点。因为这些资源对象扮演者独一无二的角色,因此如何绕过常规的构造器,不让资源的调用者随意创建,这就需要一种机制来保证该资源对象只有一个 实例。单例模式的意图就是提供这种机制,保证一个类仅有一个实例,并提供一个访问它的全局访问点。  

  模型图

    逻辑模型图:

              

    物理模型图:

                                         

  实现实践

一、简单实现

复制代码
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类的一个静态成员来完成,这样就实现了延迟初始化,是值得推荐的一种实现方式

  

 

 

0 0
原创粉丝点击