小白看单例模式

来源:互联网 发布:阳西县2017年网络问政 编辑:程序博客网 时间:2024/06/18 06:33
  设计模式这个名词并不是由传统的计算机人员发明的,而是由一个外国的建筑学家所写的一本名为《永恒的建筑之道》提出来的名词,在书中他定义了设计模式的定义。按照他的定义来说,设计模式一般包含三方面的概念,分别是应用场景、问题以及解决方法。在这其中的应用场景应该就是在计算机程序中容易出现此类问题的部分,换个角度来将也可以说我们可以通过参照问题发生的部分来选择合适的设计模式,剩下的问题与解决方法通过字面的意思就可以懂得含义,其中问题就是发生了什么问题,解决方法就是发生了这类问题所对应的解决方法
  单例模式是用于保证当软件系统模式中只存在一个实例的时候如何使用,它是属于一种23中种设计模式中的一种创建型设计模式,它的应用场景一般运用于全局共享资源,这种资源可能是只有一份,例如多台计算机共享同一台打印机时,打印机就是一种全局共享资源,同时对于多台计算机所连接的局域网来说,它只有一份,又可能是这种资源可以创建多份,但是每次创建资源都要花费一定的资源,但创建资源较少的情况下,可能影响系统的性能并不大,但当数量达到一定的程度时就会给系统带来巨大的负担,例如在我们访问网站的,网站的每一个网页都会有一个日期,若每个网页都是单独创建一个日期的对象,这样的话,会影响到网站服务器的性能。这时候,我们可以将日期对象作为全局共享资源,让一个日期对象同时被多个网张网页共享,这样会大大降低网站的性能。在这里读者需要分清什么是全局共享资源,在广义上全局共享资源可以是CPU,可以是CPU提供的时间片,也可以一个单独的地址空间块,更或者是一个计算机的部件,例如我前面所说的打印机,从狭义上看,全局共享资源可以是java项目中的字符串池,或者是一个工厂对象,例如数据库连接中的DriverManager。
   一般的单例模式分为两种类型,一种称为懒汉模式,一种称为饿汉模式,除此之外网上也有一种称为登记单例的模式,但较少人用,所以在这里并不讲,首先将的懒汉模式,为什么称为懒汉模式是因为使用这种模式想要获取的共享资源(这里说的共享资源其实指的是一个类的实例化对象,就像上文所说的多个网页共用的一个日期对象)在第一次调用获取资源方法的时候才会创建,换句话说若你一直不调用这个方法的话,那共享资源对象就不会创建,所以就称为懒汉模式
   最简单的实现懒汉模式便为以下这一种写法,在常规的笔试中你可以这样写,建议不要修改里面任意代码,只有这样写才会显得专业。
 
   

 

   但这种会存在线程不安全的情况,当多个线程同时调用获取资源方法便可能会将共享资源创建多份,在这里我们要对它进行优化,首先考虑的是加入同步锁,这样可以避免多线程并发,但会产生线程阻塞,影响到性能,在这里我使用二次判断尽可能将线程阻塞所带来的影响降到最低,优化代码如下


  如果想再进行优化功能可以考虑到最极限的情况,例如A、B两个线程分别进入第一个if和第二个if语句中,当线程B创建完共享资源以后,因为资源属性被volatile修饰,所以当它获取值时所有线程都可见,这时A线程在第一个if语句里执行时便立即受到属性被赋值,所以if的结果为false,即资源属性不为空,所以不需要再继续执行If的内容,修改如下图所视


另一种模式便是饿汉模式,它适用于对象小,但频繁使用,相比于懒汉模式,对象在类信息加载到内存中,便已经被创建,不存在线程安全的问题,具体代码如下:


但这种传统的饿汉模式也存在缺陷,例如要调用Singleton03类中的静态方法,不需要创建这个对象,而使用上面的方法只要类信息一加载到内存中,便会创建这个对象,降低了系统的性能,所以可以采用延迟加载,当调用其他类静态方法的时候不会自动创建类对象,只有调用非静态方法时才会创建对象,延迟加载代码具体如下

也可以使用枚举来实现饿汉模式,在枚举中构造方法是默认为私有的,类对象在类信息加载到内存时自动创建,具体实现代码如下


通过对比懒汉模式以及饿汉模式可以发现,饿汉模式不存在线程安全的问题,而懒汉模式存在线程安全的问题,饿汉模式更适合于资源对象较小,且使用频繁,而懒汉模式更使用于对象较大,较少使用


原创粉丝点击