首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > Web前端 >

Java单例模式完全辨析

2013-10-08 
Java单例模式完全剖析单例模式的类图 正如你在上图中所看到的,这不是单例模式的完整部分。此图中单例类保持

Java单例模式完全剖析

单例模式的类图

正如你在上图中所看到的,这不是单例模式的完整部分。此图中单例类保持了一个对唯一的单例实例的静态引用,并且会从静态getInstance()方法中返回对那个实例的引用。
例1显示了一个经典的单例模式的实现。
例1.经典的单例模式

?Java单例模式完全辨析Java单例模式完全辨析

    ?Java单例模式完全辨析Java单例模式完全辨析
      ?Java单例模式完全辨析Java单例模式完全辨析


        例2两次调用ClassicSingleton.getInstance(),并且把返回的引用存储在成员变量中。方法testUnique()会检查这些引用看它们是否相同。例3是这个测试案例的输出:
        例3.是这个测试案例的输出

        ?Java单例模式完全辨析Java单例模式完全辨析
          ?Java单例模式完全辨析Java单例模式完全辨析
            ?Java单例模式完全辨析Java单例模式完全辨析


              除了在这个清单中的单例类强制使用了一个多线程错误处理,例4类似于例1中的单例类。在getInstance()方法第一次被调用时,调用这个方法的线程会休眠50毫秒以便另外的线程也有时间调用getInstance()并创建一个新的单例类实例。当休眠的线程觉醒时,它也会创建一个新的单例类实例,这样我们就有两个单例类实例。尽管例4是人为如此的,但它却模拟了第一个线程调用了getInstance()并在没有完成时被切换的真实情形。
              例5测试了例4的单例类:
              例5.失败的测试

              ?Java单例模式完全辨析Java单例模式完全辨析
                ?Java单例模式完全辨析Java单例模式完全辨析
                  ?Java单例模式完全辨析Java单例模式完全辨析

                    在同步化getInstance()方法后,我们就可以得到例5的测试案例返回的下面的结果:
                    ?Java单例模式完全辨析Java单例模式完全辨析
                      ?Java单例模式完全辨析Java单例模式完全辨析
                        ?Java单例模式完全辨析Java单例模式完全辨析
                          ?Java单例模式完全辨析Java单例模式完全辨析
                            ?Java单例模式完全辨析Java单例模式完全辨析
                              ?Java单例模式完全辨析Java单例模式完全辨析


                                这段代码的基类首先创建出子类的实例,然后把它们存储在一个Map中。但是基类却得付出很高的代价因为你必须为每一个子类替换它的getInstance()方法。幸运的是我们可以使用反射处理这个问题。

                                使用反射

                                在例9的带注册表的单例类中,使用反射来实例化一个特殊的类的对象。与例8相对的是通过这种实现,Singleton.getInstance()方法不需要在每个被实现的子类中重写了。
                                例9 使用反射实例化单例类
                                ?Java单例模式完全辨析Java单例模式完全辨析


                                  关于单例类的注册表应该说明的是:它们应该被封装在它们自己的类中以便最大限度的进行复用。


                                  封装注册表

                                  例10列出了一个单例注册表类。
                                  例10 一个SingletonRegistry类

                                  ?Java单例模式完全辨析Java单例模式完全辨析


                                    注意我是把SingletonRegistry类作为一个单例模式实现的。我也通用化了这个注册表以便它能存储和取回任何类型的对象。例11显示了的Singleton类使用了这个注册表。
                                    例11 使用了一个封装的注册表的Singleton类

                                    ?Java单例模式完全辨析Java单例模式完全辨析
                                      ?Java单例模式完全辨析Java单例模式完全辨析
                                        ?Java单例模式完全辨析Java单例模式完全辨析
                                          ?Java单例模式完全辨析Java单例模式完全辨析


                                            前面这个测试案例序列化例12中的单例类,并且两次重构它。然后这个测试案例检查看是否被重构的单例类实例是同一个对象。下面是测试案例的输出:

                                            ?Java单例模式完全辨析Java单例模式完全辨析
                                              Buildfile:?build.xml? ???? ??init:? ???????[echo]?Build?20030422?(22-04-2003?11:32)? ???? ??compile:? ???? ??run-test-text:? ???????[java]?.INFO?main:?testing?singleton?serialization...? ???????[java]?.INFO?main:?testing?singleton?uniqueness...? ???????[java]?INFO?main:?checking?singletons?for?equality? ???? ???????[java]?Time:?0.1? ???? ???????[java]?OK?(2?tests)???
                                            Buildfile: build.xml ??init: ???? [echo] Build 20030422 (22-04-2003 11:32) ??compile: ??run-test-text: ???? [java] .INFO main: testing singleton serialization... ???? [java] .INFO main: testing singleton uniqueness... ???? [java] INFO main: checking singletons for equality ?????? [java] Time: 0.1 ?????? [java] OK (2 tests) 


                                            单例模式结束语

                                            单例模式简单却容易让人迷惑,特别是对于Java的开发者来说。在这篇文章中,作者演示了Java开发者在顾及多线程、类载入器和序列化情况如何实现单例模式。作者也展示了你怎样才能实现一个单例类的注册表,以便能够在运行期指定单例类。

热点排行