`
zs15932616453
  • 浏览: 27527 次
文章分类
社区版块
存档分类
最新评论

几种常用的单例模式详解

 
阅读更多

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、单例的应用,应该注意是众所周知的,否则很容易在用的时候出现思维定式的错误。
分享到:
评论

相关推荐

    单例模式.ppt

    单例模式,您能写出几个呢?这个PPT将为你全面阐述5种不同形式的单例模式。

    Python单例模式实例详解

    主要介绍了Python单例模式,结合实例形式分析了单例模式的概念、实现与使用方法、已经相关注意事项,需要的朋友可以参考下

    IOS Swift3 四种单例模式详解及实例

    Swift3 单例模式 常见的有这么几种方法 第一种简单到爆的 final class Single: NSObject { static let shared = Single() private override init() {} } final关键字的作用是这个类或方法不希望被继承和重写 ...

    Java单例模式实现的几种方式

    主要介绍了Java单例模式实现的几种方式的相关资料,需要的朋友可以参考下

    面试官的一道简单的单例模式问题给我问懵了,详解单例模式双重检查加锁为什么要加volatile关键字!

    面试官:说说单例模式几种写法? 我:懒汉式和饿汉式,懒汉式巴拉巴拉,饿汉式巴拉巴拉。 面试官:我们都知道synchronized加锁是比较耗费资源的,你这种写法每次访问都需要获得锁(基础的懒汉式写法),效率比较低,...

    详解Java中如何正确书写单例模式

    一般单例都是五种写法:懒汉,饿汉,双重校验锁,静态内部类和枚举。本文整理了几种常见的单例写法,下面跟着小编一起来看下吧

    Python实现Singleton模式的方式详解

    本文将简要介绍一下python中实现单例模式的几种常见方式和原理。一方面可以加深对python的理解,另一方面可以更加深入的了解该模式,以便实际工作中能更加灵活的使用单例设计模式。 本文将介绍常见的实现单例模式的...

    详解java中的6种单例写法及优缺点

    在java中,单例有很多种写法,面试时,手写代码环节,除了写算法题,有时候也会让手写单例模式,这里记录一下单例的几种写法和优缺点。需要的朋友可以参考下

    吴天雄--Spring笔记.doc

    IOC详解,Spring环境搭建,Spring创建Bean的三种方式,scope属性详解(包含单例设计模式),DI详解,Spring的几种注入方式,利用Spring简化Mybatis;第二天内容:AOP(AOP常用概念、Spring的三种aop实现方式、代理...

    基于Python中单例模式的几种实现方式及优化详解

    下面小编就为大家分享一篇基于Python中单例模式的几种实现方式及优化详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

    C++中的RAII机制详解

    在写C++设计模式——单例模式的时候,在写到实例销毁时,设计的GC类是很巧妙的,而这一巧妙的设计就是根据当对象的生命周期结束时会自动调用其析构函数的,而这一巧妙的设计也是有专业的名词的——RAII。那以下将...

    PHP类与对象后期静态绑定操作实例详解

    比如service层单例模式,使用后期静态绑定就非常好实现。 自 PHP 5.3.0 起,PHP 增加了一个叫做后期静态绑定的功能,用于在继承范围内引用静态调用的类。 准确说,后期静态绑定工作原理是存储了在上一个“非转发调用...

    精通QTP——自动化测试技术领航

    1.6.5 几种常见对象无法识别或识别错误的原因 168 1.6.6 总结 170 1.7 描述性编程(Descriptive Programming) 171 1.7.1 一点都不高深的描述性编程技术 172 1.7.2 掌握描述性编程的两种写法 173 1.7.3 Object ...

    php网络开发完全手册

    5.7.2 单例模式(Singleton Pattern) 81 5.7.3 工厂模式(Factory Pattern) 83 5.8 接口与抽象类 86 5.8.1 接口的定义 86 5.8.2 单一接口的实现 87 5.8.3 多重接口的实现 87 5.8.4 抽象类 88 5.9 小结 90 第6章 ...

    java面试题,180多页,绝对良心制作,欢迎点评,涵盖各种知识点,排版优美,阅读舒心

    【基础】Java 中定义常量的几种方法 25 【基础】什么时候使用字节流?什么时候用字符流? 26 【基础】GBK与UTF-8的区别 26 【基础】static、final、const的区别 26 final: 26 static: 27 【基础】如何实现对象克隆?...

    【05-面向对象(下)】

    •抽象类代表了一种未完成的类设计,它体现的是一种模板。 •抽象类与模板模式。 接口的概念 •接口定义的是多个类共同的行为规范,这些行为是与外部交流的通道,这就意味着接口里通常是定义一组公用的 ...

Global site tag (gtag.js) - Google Analytics