zoukankan      html  css  js  c++  java
  • 几种常用的单例模式详解

     

    Visual Basic .NET Visual C# .NET都属于.NET平台下的语言,它们之间的本质区别较小,区别基本都是语法结构上的,既然两种语言都属于.NET平台,并且最终都是通过MSILCLR机制来运行,要实现它们之间的转换并不难。

     

    首先看一下单例的模型

    逻辑模型图:

     

    物理模型图:

     

    单例模式的五种写法。

     

    1.简单实现

    这种方式创建的对于多线程来讲可能是不安全的,原因是如果某一时刻实例未创建,这时有多个线程在这一时刻同时判断出实例不存在,那么这些线程就会执行后续代码并对实例进行创建,这样必然会导致创建多个实例。

    C# Code

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

    VB Code

    Public NotInheritable Class Singleton 
        Shared m_instance As Singleton = Nothing
      
        Private Sub New() 
        End Sub
      
        Public Shared ReadOnly Property Instance() As Singleton 
            Get
                If m_instance Is Nothing Then
                    m_instance = New Singleton() 
                End If
                Return m_instance 
            End Get
        End Property
    End Class
    

    2.安全的线程

    这种方式可以避免简单实现中可能创建多个实例的问题,原因就是由于有Lock或者SyncLock的存在。它的含义就是将一个对象锁定,使访问它的线程在同一时刻只能是一个而不能是多个,其它线程要想访问被锁定的对象,那么必须等到被锁定的对象释放为止。

    这种做法是会影响性能的,原因就是不管实例是否创建,每次调用创建方法的时候都需要加锁,而这是没有必要的。

    在代码中被锁定的对象是事先创建的也就是先New的,原因就是保证加锁的时候,被锁定的对象已经创建,否则如果该对象未创建就加锁会出错的,这一点请读者用的时候一定注意。

    C# Code

    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; 
                } 
            } 
        } 
    }
    

    VB Code

     

    Public NotInheritable Class Singleton 
        Shared m_instance As Singleton = Nothing
        Shared ReadOnly padlock As New Object() 
      
        Private Sub New() 
        End Sub
      
        Public Shared ReadOnly Property Instance() As Singleton 
            Get
                SyncLock  padlock 
                    If m_instance Is Nothing Then
                        m_instance = New Singleton() 
                    End If
                    Return m_instance 
                End SyncLock
            End Get
        End Property
    End Class
    

     

    3.双重锁定

    这种方式的与安全线程的区别就是并不是每次都加锁,而是在加锁之前加了一个判断,即先判断是否创建了实例,如果没有创建实例被那么再加锁。

    而为什么会有第二重的判断是否存在实例呢,这也涉及到多线程的问题,具体是因为,当实例没有被创建时,多个线程通过第一层判断,这时只有一个线程锁定对象,并且创建单例对象,注意此时其它的线程并没有退回到第一层的判断之外,而是依然驻留在被锁定对象的外围等待被锁定的对象释放,假如这时被锁定的对象释放了,那么如果没有第二层的判断实例是否存在,则会出现另一个线程创建的第二实例,同理如果其他的线程也通过了第一层的判断,那么第三,第四等多个实例也会被创建,所以存在双层判断是必须的。

    C# Code

    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; 
            } 
        } 
    }
    

    VB Code 

    Public NotInheritable Class Singleton 
        Shared m_instance As Singleton = Nothing
        Shared ReadOnly padlock As New Object() 
      
        Private Sub New() 
        End Sub
      
        Public Shared ReadOnly Property Instance() As Singleton 
            Get
                If m_instance Is Nothing Then
                    SyncLock padlock 
                        If m_instance Is Nothing Then
                            m_instance = New Singleton() 
                        End If
                    End SyncLock
                End If
                Return m_instance 
            End Get
        End Property
    End Class
    

    4.静态初始化(首选方式)

    注意:代码简单是这种创建方式的最大优点。这种方式的创建被称为饿汉式单例类,之所以这样称,是站在CPU占用来讲的,首先从它的创建来看,这种方式创建的单例类是在类被加载的时候就实例化,就像饿汉一样,一点时间都不浪费的疯狂占用CPU。而前面介绍的的单例类的创建被称为懒汉式单例类,这种方式创建的单例类的实例化是要在第一次引用的时候才创建,就像个懒汉一样,能不创建就不创建,能托就托。

    通过代码可以明显看出这种方式的实例对象在开始定义的时候是用了New关键字实例化了的,而这点也是饿汉与懒汉的区别。

    它的缺点也是因为饿汉对CPU的占用导致出现在引用之前,导致我们对它的实例化很难控制,并不能按照我们想的仅仅在需要的时候实例化。

    C# Code

    public sealed class Singleton 
    { 
         static readonly Singleton instance=new Singleton(); 
       
         static Singleton() 
         { 
         } 
       
         Singleton() 
        { 
        } 
      
        public static Singleton Instance 
        { 
            get
            { 
                return instance; 
            } 
        } 
    }
    

    VB Code

     

    Public NotInheritable Class Singleton 
        Shared ReadOnly m_instance As New Singleton() 
      
        Shared Sub New() 
        End Sub
      
        Private Sub New() 
        End Sub
      
        Public Shared ReadOnly Property Instance() As Singleton 
            Get
                Return m_instance 
            End Get
        End Property
    End Class
    

    5.延迟初始化(比较常用)

    这点好处就是在代码简化的同时,将单例的实例化延迟到第一次引用,这样相对静态初始化来说,则明显要高明很多。

    C# Code

    public sealed class Singleton 
     { 
         Singleton() 
         { 
         } 
       
         public static Singleton Instance 
         { 
             get
            { 
                return Nested.instance; 
            } 
        } 
          
        class Nested 
        { 
            static Nested() 
            { 
            } 
      
            internal static readonly Singleton instance = new Singleton(); 
        } 
    }
    

    VB Code

    Public NotInheritable Class Singleton 
        Private Sub New() 
        End Sub
      
        Public Shared ReadOnly Property Instance() As Singleton 
            Get
                Return Nested.instance 
            End Get
        End Property
      
        Private Class Nested 
            Shared Sub New() 
            End Sub
      
            Friend Shared ReadOnly instance As New Singleton() 
        End Class
    End Class
    

    注意:
    1、单例模式用的时候并不像我们平时用的那样,直接New一下就可以了,它需要根据具体的情况通过单例类的方法来创建。
    2、单例类并没有改进单例类的创建,仅仅是将类限制在类内部而已。
    3、以上单例类并没有考虑对象的销毁和垃圾的回收,当然对于.Net的自动垃圾回收和对象销毁来说,这一点不需考虑,但是对于其他平台开发的情况则需注意。
    4、单例的应用,应该注意是众所周知的,否则很容易在用的时候出现思维定式的错误。 
  • 相关阅读:
    转载:USB1.1与USB2.0接口区别及识别
    漏洞利用
    ftp命令及登录
    转贴:厉害的BHO
    ip地址祥解
    windows xp最基本启动项目
    转载:小小技巧
    光驱能否刻录的查看方式
    转载:鲜为人知的Windows“插件”MSI
    转载:日常保健
  • 原文地址:https://www.cnblogs.com/zs234/p/3233391.html
Copyright © 2011-2022 走看看