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

  • 相关阅读:
    php简单的server登陆验证
    CentOS更新php(PHP 5.2+ is required问题)
    CentOS 5.5 x86_64下安装oci8与pdo_oci扩展
    httpd.conf详解
    Thinkphp中去除URL里的index.php
    Oracle使用虚拟表dual一次插入多条记录【摘录】
    【问题】apache目录403错误
    mysql中存储引擎MyISAM与InnoDB的一些区别
    从开辟蓝海到保卫蓝海(三)
    答MM问:经济泡沫破了不更好吗?
  • 原文地址:https://www.cnblogs.com/shaosks/p/2391288.html
Copyright © 2011-2022 走看看