zoukankan      html  css  js  c++  java
  • 设计模式之五:单例模式(Singleton Pattern)

    单例模式的意思就是只有一个实例。单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。

    单例模式有三个要点:

    1. 点某个类只能有一个实例;
    2. 它必须自行创建这个实例
    3. 它必须自行向整个系统提供这个实例。

    一些资源管理器常常设计成单例模式。

    C#中的单例模式 保证一个类仅有一个实例,并提供一个访问它的全局访问点

    实现要点:

    1. 单例模式是限制而不是改进类的创建。
    2. 单例模式一般不要支持Icloneable接口,因为这可能导致多个对象实例,与单例模式的初衷违背。
    3. 单例模式一般不要支持序列化,这也可能导致多个对象实例。
    4. 单例模式只考虑了对象创建的管理,没有考虑到销毁的管理,就支持垃圾回收的平台和对象的开销来讲,我们一般没必要对其销毁进行特殊的管理。
    5. 理解和扩展单例模式的核心是“如果控制用户使用new对一个类的构造器的任意调用”

    优点:

    1. 实例控制:Singleton会阻止其他对象实例化其自己的Singleton对象的副本,从而确保所有对象都访问唯一实例。
    2. 灵活性:因为类控制了实例化过程,所以类可以更加灵活修改实例化过程。

    缺点:

    1. 对象生存期:Singleton不能够解决删除单个对象的问题。在提供内存管理的语言中(例如基于.NET Framework的语言),只有Singleton类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(例如C++),其他类可以删除。但这样会导致Singleton类中出现悬浮引用。

    实用性:

    当类只有一个实例而且客户可以从一个总所周知的访问点访问它时。

       当这个唯一实例应该是通过子类化可扩展的,并且客户应该无需更改代码就能使用一个扩展的实例时。

    应用场景:

    1. 每台计算机可以有若个干打印机,但只能有一个Printer Spooler,避免两个打印机作业同时输出到打印机。
    2. PC机中可能有几个串口,但只能有一个Com1口的实例。
    3. 系统中只能有一个窗口管理器
    4. .NET Remoting中服务器激活对象中Singleton对象,确保所有客户程序的请求只有一个实例来处理。
    5.  

    单例模式的几种经典实现方式:

    1. public sealed class Singleton

    {

        static Singleton instance=null;

     

        Singleton()

        {

        }

     

        public static Singleton Instance

        {

            get

            {

                if (instance==null)

                {

                    instance = new Singleton();

                }

                return instance;

            }

        }

    }

    这是最简单的实现方式 ,但该实现对线程来说是不安全的,当有两个或多个线程同时判断instance==null并且得到结果都为true,就会创建多个实例,这就违背了单例模式的原则。实际上在上述代码中,有可能在计算出表达式的值之前,对象实例已经被创建,但是内存模型并不能保证对象实例在第二个线程创建之前被发现。

    该实现方式直到要求产生一个实例才执行实例化,这种方法称为“惰性实例化”,惰性实例化避免了在应用程序启动时实例化不必要的singleton.

    2.

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

    这种实现方式对线程来说是安全的,但是这种实现方式增加了额外的开销,损失了性能。

    3.

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

    这种实现方式对线程来说是安全的,同时线程不是每次都加锁,只有判断对象实例没有创建时它才加锁。解决了线程并发的问题,但是无法实现延迟初始化。

    4.

    public sealed class Singleton
    {
        static readonly Singleton instance=new Singleton();
     
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static Singleton()
        {
        }
     
        Singleton()
        {
        }
     
        public static Singleton Instance
        {
            get
            {
                return instance;
            }
        }
    }

    该实现方式在第一次引用类的成员时创建实例。公共语言运行库负责处理变量初始化。该方法的缺点是:对实例化机制的控制权较少。在大多数情况下,静态初始化是在.NET中实现Singleton的首选方法。

    5. public sealed class Singleton

    {

        Singleton()

        {

        }

     

        public static Singleton Instance

        {

            get

            {

                return Nested.instance;

            }

        }

       

        class Nested

        {

            // Explicit static constructor to tell C# compiler

            // not to mark type as beforefieldinit

            static Nested()

            {

            }

     

            internal static readonly Singleton instance = new Singleton();

        }

    }

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

  • 相关阅读:
    React在componentDidMount里面发送请求
    React 术语词汇表
    React里受控与非受控组件
    React和Vue等框架什么时候操作DOM
    【LeetCode】79. Word Search
    【LeetCode】91. Decode Ways
    【LeetCode】80. Remove Duplicates from Sorted Array II (2 solutions)
    【LeetCode】1. Two Sum
    【LeetCode】141. Linked List Cycle (2 solutions)
    【LeetCode】120. Triangle (3 solutions)
  • 原文地址:https://www.cnblogs.com/shaosks/p/2391288.html
Copyright © 2011-2022 走看看