zoukankan      html  css  js  c++  java
  • 设计模式学习之路——Singleton 单件模式

    在程序设计过程中,有很多情况需要保证一个类只有一个实例.这时候就需要使用单件模式了。

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

    结构(Struct)

     

     

     

    1 使用静态方法创建单件

    让一个类只有一个实例,最容易的方法是在类中嵌入一个静态变量,并在第一个类实例中设置该变量,而且每次进入构造函数都要检查。不管类有多少个实例,静态变量只能有一个实例。为了防止类被多次实例化,我们把构造函数声明为私有的,这样只能在类的静态方法里创建一个实例。

    单线程环境下Singleton模式的实现

     

    代码
    public class Singleton
        {
            
    private static Singleton instance;
            
    private Singleton() {}

            
    public static Singleton Instance
            {
                
    get 
                {
                    
    if (instance == null)
                    {
                        instance 
    = new Singleton();
                    }
                    
    return instance;
                }
            }    
    }

     

     

    单线程Singleton模式的几个要点

    1. Singleton模式中的实例构造器可以设置为protected以允许子类派生。

    2. Singleton模式一般不要支持Icloneable接口,因为这可能导致多个对象实例,与Singleton模式的初衷违背。

    3. Singleton模式一般不要支持序列化,因为这也有可能导致多个对象实例,同样与Singleton模式的初衷违背。

    4. Singleton模式只考虑到了对象创建的管理,没有考虑对象销毁的管理。就支持垃圾回收的平台和对象的开销来将,我们一般没有必要对其销毁进行特殊的管理。

    5. 不能应对多线程环境:在多线程环境下,使用Singleton模式仍然有可能得到Singlet类的多个实例对象。

     

     

    多线程环境下Singleton模式实现

     
    代码
    public class Singleton
        {
            
    private static volatile Singleton instance;
            
    private static object lockHelper = new object();

            
    private Singleton() { }

            
    public static Singleton Instance
            {
                
    get
                {
                    
    if (instance == null)
                    {
                        
    lock (lockHelper)
                        {
                            
    if (instance == null)
                            {
                                instance 
    = new Singleton();
                            }
                        }
                    }
                    
    return instance;
                }
            }
        }
    代码
    public class Singleton
        {
            
    public static readonly Singleton Instance;

            
    static Singleton()
            {
                Instance 
    = new Singleton();
            }

            
    private Singleton() { }

        }

    上面的方式等同于下面的实现方式:

     

    public class Singleton
        {
            
    public static readonly Singleton Instance= new Singleton();
            
    private Singleton() { }

        }

     

     

     

     

    2 提供一个单件的全局访问点

    由于使用单件可以提供一个类的全局访问点,即使C#中没有全局变量,设计程序时也必须为整个程序提供引用单件的方法。

    一种解决方案是在程序的开头创建单件,并将其作为参数传递到需要使用它的类中。

     
         Singleton instance = Singleton.Instance;
         Test test
    = new Test(instance);

     

     

    这种方法的缺点是,在某次程序运行中,可能不需要所有的单件,,这样会影响程序的性能。

    另一种更灵活的解决方案是,在程序中创建一个所有单件类的注册表,并使注册表始终是可用的,每次实例化一个单件,都将其记录在注册表中。程序的任何部分都能使用标识字符串访问任何一个单件实例,并能取回相应的实例变量。

    注册表方法的缺点是减少了类型检查,因为注册表中的单件表可能把所有的单件都保存成对象类型,例如,hashtable中的对象类型,另外,注册表本身也有可能是一个单件,必须使用构造函数或者其他set函数把他传递给程序的所有部分。

    提供一个全局访问点的最常用方式是使用类的静态方法。类名始终是可用的,静态方法只能由类调用,不能由类的实例调用,所以,不管程序中有多少个地方调用该方法,永远只能有一个这样的类实例。

  • 相关阅读:
    改造二叉树
    汽车加油行驶问题
    [SHOI2012]回家的路
    子串
    P3558 [POI2013]BAJ-Bytecomputer
    HDU
    UVALive
    ZOJ
    HDU
    牛客小白月赛2 题解
  • 原文地址:https://www.cnblogs.com/luoht/p/1750278.html
Copyright © 2011-2022 走看看