千家信息网

C#中怎么实现单例模式

发表于:2024-11-24 作者:千家信息网编辑
千家信息网最后更新 2024年11月24日,这期内容当中小编将会给大家带来有关C#中怎么实现单例模式,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。单例模式的介绍2.1、动机(Motivate)在软件系统中,经
千家信息网最后更新 2024年11月24日C#中怎么实现单例模式

这期内容当中小编将会给大家带来有关C#中怎么实现单例模式,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

单例模式的介绍


2.1、动机(Motivate)

在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性、以及良好的效率。

   如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?

这应该是类设计者的责任,而不是使用者的责任

2.2、意图(Intent)

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

2.3、结构图(Structure)

2.4、模式的组成

(1)、单件实例(Singleton):这个模式里面只有一个类型,就是Singleton类型,并且这个类只有一个实例,可以通过Instance()方法获取该类型的实例。

2.5、单件模式的代码实现

既然是单实例,肯定会涉及到多线程的问题,我们就一步一步的来写代码,我们先看看单线程Singleton模式的实现,代码如下:

私有的实例构造器是屏蔽外界的调用,上面的单例模式的实现在单线程下确实是完美的,也很好的满足了我们单线程环境的需求。

单线程单例模式的几个要点:

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

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

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

(4)、Singletom模式只考虑到了对象创建的工作,没有考虑对象销毁的工作。为什么这样做呢,因为Net平台是支持垃圾回收的,所以我们一般没有必要对其进行销毁处理。

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


如果放在多线程环境下,问题就出来了。因为在两个线程同时运行GetInstance方法时,此时两个线程判断(uniqueInstance ==null)这个条件时都返回真,此时两个线程就都会创建Singleton的实例,这样就违背了我们单例模式初衷了。要想解决这个问题,只要让GetInstance方法在同一时间只运行一个线程运行就好了,让我们看看多线程Singleton模式的实现,代码如下:

上面这种解决方案确实可以解决多线程的问题,但是上面代码对于每个线程都会对线程辅助对象locker加锁之后再判断实例是否存在,对于这个操作完全没有必要的,因为当第一个线程创建了该类的实例之后,后面的线程此时只需要直接判断(uniqueInstance==null)为假,此时完全没必要对线程辅助对象加锁之后再去判断,所以上面的实现方式增加了额外的开销,损失了性能,为了改进上面实现方式的缺陷,我们只需要在lock语句前面加一句(uniqueInstance==null)的判断就可以避免锁所增加的额外开销,这种实现方式我们就叫它 "双重锁定(Double Check)",下面具体看看实现代码的:

volatile修饰:编译器在编译代码的时候会对代码的顺序进行微调,用volatile修饰保证了严格意义的顺序。一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。

三、C#中实现了单例模式的类

现在我们看看,如何使用C#语言的特性来实现单例的Singleton模式。

内联初始化其实是把静态的字段放到静态构造器去初始化。只要想访问静态字段,必定已经在之前执行了静态构造器。这样也能够精确地保证使用的时候一定能拿到实例,如果不使用也不会实例化对象,也就是延时加载的功能。他同样能够支持多线程环境,因为只可能有一个线程执行静态构造器,不可能有多个线程去执行静态构造器,感觉就是程序已经自动为我们加锁了。

它的一点弊端就是它不支持参数化的实例化方法。在.NET里静态构造器只能声明一个,而且必须是无参数的,私有的。因此这种方式只适用于无参数的构造器。

需要说明的是:HttpContext.Current就是一个单例,他们是通过Singleton的扩展方式实现的,他们的单例也并不是覆盖所有领域,只是针对某些局部领域中,是单例的,不同的领域中还是会有不同的实例。

四、Singleton模式的扩展

(1)、将一个实例扩展到n个实例,例如对象池的实现。(n不是指无限个实例,而是固定的某个数)

(2)、将new构造器的调用转移到其他类中,例如多个类协同工作环境中,某个局部环境只需要拥有某个类的一个实例。

(3)、理解和扩展Singleton模式的核心是"如何控制用户使用new对一个类的实例构造器的任意调用"。

五、单例模式的实现要点

1、Singleton模式是限制而不是改进类的创建。

2、Singleton类中的实例构造器可以设置为Protected以允许子类派生。

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

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

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

6、理解和扩展Singleton模式的核心是"如何控制用户使用new对一个类的构造器的任意调用"。

7、可以很简单的修改一个Singleton,使它有少数几个实例,这样做是允许的而且是有意义的。

1】、单例模式的优点:

(1)、实例控制:Singleton 会阻止其他对象实例化其自己的 Singleton 对象的副本,从而确保所有对象都访问唯一实例

(2)、灵活性:因为类控制了实例化过程,所以类可以更加灵活修改实例化过程

2】、单例模式的缺点:

(1)、开销:虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题。

(2)、可能的开发混淆:使用 singleton 对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用 new 关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。

(3)、对象的生存期:Singleton 不能解决删除单个对象的问题。因为它包含对该静态的私有字段的引用,静态字段是不能被CLR回收内存的,该实例会和应用程序生命周期一样长,一直存在。

3】、单例模式的使用场合:

(1)、当类只能有一个实例而且客户可以从一个众所周知的访问点访问它时。

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


上述就是小编为大家分享的C#中怎么实现单例模式了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注行业资讯频道。

0