• 01.Singleton单件(单例)


    一:动机(Motivation)

    <1>在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性、以及良好的效率。
    <2>如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?
    <3>这应该是类设计者的责任,而不是使用者的责任。

    二:意图(Intent)

    保证一个类仅有一个实例,并提供一个该实例的全局访问点。
    ——《设计模式》GoF

    三:结构(Structure)

    四:结构详解

    五:生活中的例子

    美国总统的职位是Singleton,美国宪法规定了总统的选举,任期以及继任的顺序。这样,在任何时刻只能由一个现任的总统。无论现任总统的身份为何,其头衔"美利坚合众国总统"是访问这个职位的人的一个全局的访问点。

    六:简单实现

    public sealed class Singleton
    {
        static Singleton instance = null;
        private Singleton()
        {
        }
    
        public static Singleton Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new Singleton();
                }
                return instance;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    <1>对于线程来说不安全
    <2>单线程中已满足要求

    优点:
    <1>由于实例是在 Instance 属性方法内部创建的,因此类可以使用附加功能;
    <2>直到对象要求产生一个实例才执行实例化;这种方法称为“惰性实例化”。惰性实例化避免了在应用程序启动时实例化不必要的 singleton。

    七:线程的安全

    public sealed class Singleton
    {
        static Singleton instance = null;
        public static readonly object padlock = new object();
    
        private Singleton()
        {
        }
    
        public static Singleton Instance
        {
            get
            {
                lock (padlock)
                {
                    if (instance == null)
                    {
                        instance = new Singleton();
                    }
                }
                return instance;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    <1>同一个时刻加了锁的那部分程序只有一个线程可以进入;
    <2>对象实例由最先进入的那个线程创建;
    <3>后来的线程在进入时(instence == null)为假,不会再去创建对象实例;
    <4>增加了额外的开销,损失了性能。

    八:双重锁定

    public sealed class Singleton
    {
        static Singleton instance = null;
        public static readonly object padlock = new object();
    
        private Singleton()
        {
        }
    
        public static Singleton Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (padlock)
                    {
                        if (instance == null)
                        {
                            instance = new Singleton();
                        }
                    }
                }
                return instance;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    <1>多线程安全;
    <2>线程不是每次都加锁;
    <3>允许实例化延迟到第一次访问对象时发生。

    九:静态初始化

    public sealed class Singleton
    {
        private static readonly Singleton instance = null;
        
        static Singleton()
        {
            instance = new Singleton();
        }
    
        private Singleton()
        {
        }
    
        public static Singleton Instance
        {
            get 
            { 
                return instance; 
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    .Net框架静态构造函数无论何时(多线程调用时),只执行一次!

    <1>依赖公共语言运行库负责处理变量初始化;
    <2>公共静态属性为访问实例提供了一个全局访问点;
    <3>对实例化机制的控制权较少(.NET代为实现);
    <4>静态初始化是在 .NET 中实现 Singleton 的首选方法。

    十:延迟初始化

    public sealed class Singleton
    {
        private Singleton()
        {
        }
    
        public static Singleton Instance
        {
            get
            {
                return Nested.instance;
            }
        }
    
        private class Nested
        {
            internal static readonly Singleton instance = null;
            static Nested()
            {
                instance = new Singleton();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    初始化工作由Nested类的一个静态成员来完成,这样就实现了延迟初始化。

    十一:注意事项

    <1>Singleton模式中的实例构造器可以设置为protected以允许子类派生。
    <2>Singleton模式一般不要支持ICloneable接口,因为这可能会导致多个对象实例,与Singleton模式的初衷违背。
    <3>Singleton模式一般不要支持序列化,因为这也有可能导致多个对象实例,同样与Singleton模式的初衷违背。
    <4>Singletom模式只考虑到了对象创建的管理,没有考虑对象销毁的管理。就支持垃圾回收的平台和对象的开销来讲,我们一般没有必要对其销毁进行特殊的管理。

    十二:总结

    <1>Singleton模式是限制而不是改进类的创建。
    <2>理解和扩展Singleton模式的核心是“如何控制用户使用new对一个类的构造器的任意调用”。
    <3>可以很简单的修改一个Singleton,使它有少数几个实例,这样做是允许的而且是有意义的。

  • 相关阅读:
    重生之我是一名程序员 34
    MATLAB中polyval函数用法
    云小课|3种常用Git工作流推荐
    Ubuntu 软件安装方法(入门必看)
    用VSC++做一个飞机大战的游戏
    动态规划算法几个小问题
    vue2中vuex的用法
    个推用户运营全新上线用户生命周期管理功能,助力APP快速实现用户精细化运营
    手把手教你做一个天猫精灵(四)
    代码大全阅读随笔(五)
  • 原文地址:https://blog.csdn.net/zzyzxb/article/details/126655295