码迷,mamicode.com
首页 > 其他好文 > 详细

设计模式(一)单例模式:实现 Serializable 接口之后的额外操作

时间:2017-09-10 19:44:22      阅读:222      评论:0      收藏:0      [点我收藏+]

标签:技术分享   creates   fail   接受   UI   adr   turn   防止   不能   

思想:

 

  如果一个单例类,无论是用什么样的方式设计,一旦被间接或者直接实现 Serializable 接口之后,就要多增加一点考虑,就是在类被反序列化之后,也要保证单例。

 

技术分享
 1 public class SerializableSingletonFail implements Serializable {
 2 
 3     private static final long serialVersionUID = 3355486892283807446L;
 4 
 5     private static final SerializableSingletonFail instance = new SerializableSingletonFail();
 6 
 7     private SerializableSingletonFail() {
 8         if (instance != null) {
 9             throw new IllegalStateException();
10         }
11     }
12 
13     public static final SerializableSingletonFail getInstance() {
14         return instance;
15     }
16 
17 }
Serializable 之后的单例

 

  以上的类,是一个单例的简单饿汉模式实现,只是实现了 Serializable 接口。从类名上看就知道,这样做不能保证单例。

 

  每一个类中,有两个很特殊的方法,分别是 writeReplace() 和 readResolve() 。

  前者保证,无论从什么对象序列化,只要是序列化这个类,都会把 writeReplace() 的返回对象序列化进文件;而后者保证,无论从什么文件反序列化,都会反序列化成 readResolve() 的返回对象。

  这两个方法,对于方法签名有着严格的限定,包括入参(没有入参)和返回类型(Object),但是可以接受抛出不同的异常。

  一旦满足以上这点,即是将方法设为 private,而且没有任何调用,编译器也不会提示警告。而且建议讲方法设为 private,防止误操作。

 

技术分享
 1 public class SerializableSingleton implements Serializable {
 2 
 3     private static final long serialVersionUID = -6451544700567522443L;
 4 
 5     private static final SerializableSingleton instance = new SerializableSingleton();
 6 
 7     private SerializableSingleton() {
 8         if (instance != null) {
 9             throw new IllegalStateException();
10         }
11     }
12 
13     public static final SerializableSingleton getInstance() {
14         return instance;
15     }
16 
17     private Object readResolve() {
18         return instance;
19     }
20 
21 }
Serializable 之后的单例,成功

 

技术分享
 1 public class SerializableSingletonTest {
 2 
 3     private final String uri1 = "./src/test/resources/serialable1.txt";
 4     private final String uri2 = "./src/test/resources/serialable2.txt";
 5 
 6     public void createSerialFile() {
 7         SerializableSingletonFail singleton1 = SerializableSingletonFail.getInstance();
 8         SerializableSingleton singleton2 = SerializableSingleton.getInstance();
 9         try (FileOutputStream fos1 = new FileOutputStream(uri1); ObjectOutputStream oos1 = new ObjectOutputStream(fos1);
10                 FileOutputStream fos2 = new FileOutputStream(uri2); ObjectOutputStream oos2 = new ObjectOutputStream(fos2);) {
11             oos1.writeObject(singleton1);
12             oos2.writeObject(singleton2);
13         } catch (Exception e) {
14             e.printStackTrace();
15         }
16     }
17 
18     @Test
19     public void testFailure() {
20         SerializableSingletonFail singleton1 = SerializableSingletonFail.getInstance();
21         SerializableSingletonFail singleton2 = null;
22         // 反序列化
23         try (FileInputStream fio = new FileInputStream(uri1); ObjectInputStream ois = new ObjectInputStream(fio);) {
24             singleton2 = (SerializableSingletonFail) ois.readObject();
25         } catch (Exception e) {
26             e.printStackTrace();
27         }
28         Assert.assertNotSame(singleton1, singleton2);
29     }
30 
31     @Test
32     public void testSuccess() {
33         SerializableSingleton singleton1 = SerializableSingleton.getInstance();
34         SerializableSingleton singleton2 = null;
35         // 反序列化
36         try (FileInputStream fio = new FileInputStream(uri2); ObjectInputStream ois = new ObjectInputStream(fio);) {
37             singleton2 = (SerializableSingleton) ois.readObject();
38         } catch (Exception e) {
39             e.printStackTrace();
40         }
41         Assert.assertSame(singleton1, singleton2);
42     }
43 
44 }
JUnit

 

设计模式(一)单例模式:实现 Serializable 接口之后的额外操作

标签:技术分享   creates   fail   接受   UI   adr   turn   防止   不能   

原文地址:http://www.cnblogs.com/jing-an-feng-shao/p/7501812.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!