浅谈单例模式_第1页
浅谈单例模式_第2页
浅谈单例模式_第3页
浅谈单例模式_第4页
浅谈单例模式_第5页
已阅读5页,还剩3页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

前言什么是单例模式?单例模式,属于创建类型的一种常用的软件设计模式。通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中属于单例,如:仅线程上下文内使用同一个实例)上面是百度百科给出的解释。大家都知道,面向对象的思想就是我们可以把一个类实例很多次,每次实例出来的都是一个对象,意味着你可以创建很多个基于这个类的对象。单例模式,说白了,就是这些对象本质都是同一个,整个程序中,不管在哪里用,使用的都是同一个实例对象。如果我们创建了一个China类,我们可以一直new吗?不可以,因为世界上只有一个China,所以我们使用的都是同一个China对象。Version1-非线程安全

publicclassChina

{

private

China()

{

}

privatestaticChinachina

=

null;

publicstaticChinaInstance

{

get

{

if

(china

==

null)

{

Console.WriteLine("实例化对象");

china

=

newChina();

}

return

china;

}

}

}最简单的实现方式如上图,创建一个私有的静态对象和私有构造方法,然后在CreateInstance方法里,加一个判断,如果为Null,就重新实例化一下,否则直接返回。这种写法从逻辑上是没问题的,但是是否会出现这个if(china==null)判断,同时执行,这样就麻烦了。所以这种写法在单线程的程序是没问题的,但是在多线程中,是可能会有问题的。我们做个测试,测试代码如下:

classProgram

{

staticvoidMain(string[]

args)

{

for

(inti

=

0;

i

<

10;

i++)

{

newTaskFactory().StartNew(()

=>

{

Chinachina

=

China.Instance;

});

Thread.Sleep(10);

}

Console.ReadLine();

}

}上面的代码,就是创建10个线程,都执行CreatInstance方法,那么最终是输出多少次Console.WriteLine("实例化对象")呢?我们测试发现,这个输出结果是不唯一的,有时候会输出5次,有时候会输出2次,但是一般都是超过1次,这个就说明对象被多次实例化了,这就违背了单例模式的原则。Version2-简单的线程安全既然出现问题,那么我们就需要做一下优化,优化之后的代码如下:

publicclassChina

{

private

China()

{

}

privatestaticChinachina

=

null;

privatestaticobjectobjlock

=

newobject();

publicstaticChinaInstance

{

get

{

lock

(objlock)

{

Console.WriteLine("执行判断");

if

(china

==

null)

{

Console.WriteLine("实例化对象");

china

=

newChina();

}

}

return

china;

}

}

}对比看下,就是加了一个同步锁,这样就可以避免同时执行的情况,并且,我们在lock里加了一个Console.WriteLine("执行判断"),观察这行代码执行多少次。从结果来看,实例化对象只执行了一次,说明对象只被创建过一次,满足了我们的需求,达到了预期的效果。Version3-双if+lock实现上面那种方式已经可以达到预期效果,但是我们注意到一个问题,执行判断这行代码被执行了10次,这显示不符合我们的逻辑,既然已经实例化了,为什么每次还要执行判断呢?是不是多此一举?并且每次请求对象,都会进行lock操作,lock对性能是有一定影响的。于是我们继续优化,优化之后的代码如下:

publicclassChina

{

private

China()

{

}

privatestaticChinachina

=

null;

privatestaticobjectobjlock

=

newobject();

publicstaticChinaInstance

{

get

{

if

(china

==

null)

{

lock

(objlock)

{

Console.WriteLine("执行判断");

if

(china

==

null)

{

Console.WriteLine("实例化对象");

china

=

newChina();

}

}

}

return

china;

}

}

}我们对比代码可以看出,就是又加了一个if(china==null),这种双if+lock的方式,是不是可以解决我们的问题呢?我们执行一次,看看结果:我们通过结果可以看到只执行了一次判断,也只执行一次实例化对象,但是我们还可以继续优化。Version4-静态变量实现话不多说,直接上代码:

publicclassChina

{

private

China()

{

}

privatestatic

readonly

Chinachina

=

newChina();

publicstaticChinaInstance

{

get

{

return

china;

}

}

}利用静态变量去实现单例,非常简单,但同时也是线程安全的,由CLR保证,在程序第一次使用该类之前被调用,而且只调用一次。但是这种方式也有缺点,就是实例化过程是在程序初始化时就执行的,而不是在使用时才执行,就是说,不管你用不用,都已经实例化了。Version5-完全懒汉式实现

publicclassChina

{

private

China()

{

}

publicstaticChinaInstance

{

get

{

return

Lazy.instance;

}

}

privateclassLazy

{

static

Lazy()

{

}

internalstatic

readonly

Chinainstance

=

newChina();

}

}这种方法与上一种方法类似,只是多加了一个类,来解决上一个版本的缺点。Version6-使用Lazy特性从.NET4开始,可以使用Lazytype来实现完全懒汉式,代码也变得更简单,代码如下:

publicclassChina

{

private

China()

{

}

privatestatic

readonly

Lazy<China>

lazy

=

newLazy<China>(()

=>

newChina());

publicstaticChinaInstance

{

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论