浅析设计模式:单例模式(Songleton)

    在实际编程中,我们可能有这样的需求:确保某个类在Java堆内存中只存在一个实例,这样的场景一般出现在该类实例作为控制器,或者在GUI编程中的视图窗口。

    本文介绍单例模式的4中常用实现方式,并分析它们各自的优缺点:

1)、饿汉式



    饿汉式实现简单,能够满足大部分应用场景,即使是在并发环境下也能够保证单例模式的正确性。

    但是饿汉式也存在一些弊端:饿汉式的实例在类加载的初始化阶段就完成实例化,这也许过早了点,因为程序中若不使用或者在较晚阶段才会使用该实例的话,过早的实例化可能会造成资源不必要的浪费,系统启动时间也会有所影响。


2)、懒汉式


     这是最原始的懒汉式,与饿汉式的区别在于,静态属性instance一开始并未实例化,因此在类加载阶段也就不会加载到内存中。其次,在getInstance静态方法中判断instance是否被实例化了,若未实例化则创建,否则直接返回,因此instance属性的实例化延迟到了运行期才完成,这很好的节省了系统的资源。

     当然,这种原始的懒汉式也存在明显的弊端,若在并发环境下,getInstance静态方法可能会"同时"被多个线程访问,因此创建多个实例,这就背离了单例模式。因此需要对原始的懒汉式进行改进:


只需要在原来的基础上作两点改进:

1、使用volatile关键字修饰静态属性instance

2、对getInstance静态方法双重校验锁优化

     优化后的懒汉式就可以满足并发环境的要求了,但是使用synchronize同步代码块可能会影响性能,可以使用ReentrantLock替代。


3)、静态内部类式


    静态内部类式是一种比较推荐的方式,程序运行时调用getInstance静态方法时,内部类才会被加载到JVM内存中,因此实例化的过程也就被延迟到了运行期。再者,利用JVM类加载机制自身的特性(类构造器<cinit>只会被调用一次),使得即使在并发环境下也能保证只会创建一个实例。

4)、使用枚举


使用枚举实现单例模式是Effective Java作者Josh Bloch 提倡的方式,解决了以下三个问题:
(1)自由序列化。
(2)保证只有一个实例。
(3)线程安全。

    上述的4中实现单例模式的方式已经介绍完毕,如何去抉择还是应当考虑具体的情况,需要特别指出的是,这几中方式并不能真正100%的保障只存在一个实例,因为java语言中创建对象的方式可不只有new,通过反射一样可以进行实例化,因此在使用单例模式时还是需要尽量避免使用反射,下面提供一个例子,讲解如何使用反射机制破解单例模式:



Ending ...大笑



猜你喜欢

转载自blog.csdn.net/someonemh/article/details/80848348