zoukankan      html  css  js  c++  java
  • 转:单例模式(序列化)

    如果你序列化一个单例类,然后两次重构它,那么你就会得到那个单例类的两个实例,除非你实现readResolve()方法,像下面这样:
    例1 一个可序列化的单例类

    Java代码
    import org.apache.log4j.Logger;   
         
    public class Singleton implements java.io.Serializable {   
       public static Singleton INSTANCE = new Singleton();   
         
       protected Singleton() {   
          // Exists only to thwart instantiation.    
       

       
       private Object readResolve() {   
                return INSTANCE;    
         
      


    上面的单例类实现从readResolve()方法中返回一个唯一的实例;这样无论Singleton类何时被重构,它都只会返回那个相同的单例类实例。

    例2测试了例1 的单例类

     

    例2 测试一个可序列化的单例类

    Java代码
    import java.io.*;   
    import org.apache.log4j.Logger;   
    import junit.framework.Assert;   
    import junit.framework.TestCase;   
         
    public class SingletonTest extends TestCase {   
       private Singleton sone = null, stwo = null;   
       private static Logger logger = Logger.getRootLogger();   
         
       public SingletonTest(String name) {   
          super(name);   
         


       public void setUp() {   
           sone = Singleton.INSTANCE;   
           stwo = Singleton.INSTANCE;   
         


       public void testSerialize() {   
           logger.info("testing singleton serialization...");    
           writeSingleton();   
           Singleton s1 = readSingleton();   
           Singleton s2 = readSingleton();   
           Assert.assertEquals(true, s1 == s2);[/b]   

        


       private void writeSingleton() {   
          try {   
              FileOutputStream fos = new FileOutputStream("serializedSingleton");   
              ObjectOutputStream oos = new ObjectOutputStream(fos);   
              Singleton s = Singleton.INSTANCE;   
         
              oos.writeObject(Singleton.INSTANCE);   
              oos.flush();   
           }catch(NotSerializableException se) {   
              logger.fatal("Not Serializable Exception: " + se.getMessage());    
           }catch(IOException iox) {   
              logger.fatal("IO Exception: " + iox.getMessage());    
             
         


       private Singleton readSingleton() {   
           Singleton s = null;   
         
          try {   
              FileInputStream fis = new FileInputStream("serializedSingleton");   
              ObjectInputStream ois = new ObjectInputStream(fis);   
              s = (Singleton)ois.readObject();   
           }catch(ClassNotFoundException cnf) {   
              logger.fatal("Class Not Found Exception: " + cnf.getMessage());   
           }catch(NotSerializableException se) {   
              logger.fatal("Not Serializable Exception: " + se.getMessage());   
           }catch(IOException iox) {   
              logger.fatal("IO Exception: " + iox.getMessage());   
            
          return s;   
         


       public void testUnique() {   
           logger.info("testing singleton uniqueness...");   
           Singleton another = new Singleton();   
         
           logger.info("checking singletons for equality");   
           Assert.assertEquals(true, sone == stwo);   
         
      


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

    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)   


    单例模式结束语

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

  • 相关阅读:
    [bzoj2654]tree_二分_kruskal
    [luogu1373]小a和uim之大逃离_动态规划
    [luogu1156]垃圾陷阱_动态规划_背包dp
    [luogu2209][USACO13]燃油经济性Fuel Economy_贪心
    UNIX环境高级编程——进程基本概述
    UNIX环境高级编程——进程控制
    UNIX环境高级编程——进程环境
    UNIX环境高级编程——时间和日期
    UNIX环境高级编程——Linux进程地址空间和虚拟内存
    UNIX环境高级编程——标准I/O库函数和Unbuffered I/O函数
  • 原文地址:https://www.cnblogs.com/phoebus0501/p/1977160.html
Copyright © 2011-2022 走看看