设计模式实践之旅——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类的一个静态成员来完成,这样就实现了延迟初始化,是值得推荐的一种实现方式

  

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值