【JAVA】:用枚举法实现单例设计模型
усил の博客 2020/5/26 Java
# 用枚举法实现单例设计模型
接着上一篇博客写到的几种设计形式下的单例设计模型,上一篇写到的分别由懒汉式(线程不安全),懒汉式(线程安全),饿汉式,双检锁/双重校验锁,登记式/静态内部类,其中的枚举法是放在这里写。
一、破解各个设计形式的单例设计模型。
(1)采用Java反射机制破解单例设计模型(枚举除外)
下面以内部静态类为例子
public class Demo5 {
//内部静态类
private static class Demo6{
private static final Demo5 demo=new Demo5();
}
private Demo5(){}
public void sayHello(){
System.out.println("登记式/静态内部类:Hello,CSDN");
}
public static final Demo5 getdemo(){
return Demo6.demo;
}
public static void main(String[] args) throws Exception {
System.out.println("正常获取实例化对象");
Demo5 demo=Demo5.getdemo();
Demo5 demo1=Demo5.getdemo();
System.out.println(demo.hashCode());
System.out.println(demo1.hashCode());
System.out.println("通过Java反射机制获取实例化对象");
Class<?> c=Class.forName("entity.Demo5");
Constructor con=c.getDeclaredConstructor(null);
//true表示反射对象应该在使用时抑制Java语言访问检查,反则为false
con.setAccessible(true);
Demo5 d1=(Demo5) con.newInstance();
Demo5 d2=(Demo5) con.newInstance();
System.out.println(d1.hashCode());
System.out.println(d2.hashCode());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
输出结果: 理论上输出的对象应该一样,但实际输出俩个不同的对象。
解决方法:
这里提供只提供懒汉式的解决方法
//在构造方法里面添加一个判断
private Demo2(){//构造方法私有化
if(demo!= null){
throw new RuntimeException();
}
}
1
2
3
4
5
6
2
3
4
5
6
(2)反序列化破解单例设计模型(枚举除外)
前提是该类应该继承Serializable接口 下面以内部静态类为例子
public class Text {
public static void main(String[] args) throws Exception {
Demo5 d1=Demo5.getdemo();
Demo5 d2=Demo5.getdemo();
System.out.print("反序列化前对象为:");
System.out.print(d1.hashCode()+" ");
System.out.println(d2.hashCode());
//将对象d1写入文件中
FileOutputStream fos=new FileOutputStream("e:"+File.separator+"mldn.txt");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(d1);
oos.close();
fos.close();
//从文件中读取对象d1
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("e:"+File.separator+"mldn.txt"));
Demo5 d3=(Demo5) ois.readObject();
System.out.println("反序列化后对象为:"+d3.hashCode());//s3是一个新对象
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
输出结果: 理论上反序列化后对象应该还是一样当实际不是。
解决方法:
//在该类添加该方法
private Object readResolve() throws ObjectStreamException{
return Demo6.demo;
}
1
2
3
4
2
3
4
处理后:
二、枚举法实现单例设计模型
枚举
public enum Demo6 {
INSTANCE;
public Demo6 getInstance(){
return INSTANCE;
}
}
1
2
3
4
5
6
2
3
4
5
6
具体类
public class User {
//私有化构造函数
private User(){ }
//定义一个静态枚举类
static enum SingletonEnum{
//创建一个枚举对象,该对象天生为单例
INSTANCE;
private User user;
//私有化枚举的构造函数
private SingletonEnum(){
user=new User();
}
public User getInstnce(){
return user;
}
}
//对外暴露一个获取User对象的静态方法
public static User getInstance(){
return SingletonEnum.INSTANCE.getInstnce();
}
public static void main(String [] args) throws Exception{
System.out.println(User.getInstance());
System.out.println(User.getInstance());
System.out.println(User.getInstance()==User.getInstance());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
输出结果: