GoF23 单例模式学习笔记
单例模式:构造即私有
饿汉式
package single;
public class Hungry {
private Hungry() {
}
private final static Hungry HUNGRY = new Hungry();
public Hungry getInstance() {
return HUNGRY;
}
}
懒汉式
package single;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class LazyMan {
private static boolean secret = false;
private LazyMan() {
synchronized (LazyMan.class) {
if(!secret) {
secret = true;
}else {
throw new RuntimeException("Bad Guy");
}
}
}
private volatile static LazyMan LAZYMAN;
public static LazyMan getInstance() {
if (LAZYMAN == null) {
synchronized (LazyMan.class) {
if (LAZYMAN == null) {
LAZYMAN = new LazyMan();
}
}
}
return LAZYMAN;
}
public static void main(String[] args) throws Exception {
Field secret = LazyMan.class.getDeclaredField("secret");
secret.setAccessible(true);
Constructor<LazyMan> constructor = LazyMan.class.getDeclaredConstructor();
constructor.setAccessible(true);
LazyMan reflectInstance1 = constructor.newInstance();
secret.set(reflectInstance1, false);
LazyMan reflectInstance2 = constructor.newInstance();
System.out.println(reflectInstance1.hashCode());
System.out.println(reflectInstance2.hashCode());
}
}
静态内部类(不安全)
package single;
public class Holder {
private Holder() {
}
public static Holder getInstance() {
return innerClass.HOLDER;
}
public static class innerClass {
private static final Holder HOLDER = new Holder();
}
}
枚举类型
package single;
import java.lang.reflect.Constructor;
public enum EnumSingle {
INSTANCE;
public EnumSingle getInstance() {
return INSTANCE;
}
public static void main(String[] args) throws Exception {
Constructor<EnumSingle> declaredConstructor = EnumSingle.class.getDeclaredConstructor(String.class, int.class);
declaredConstructor.setAccessible(true);
EnumSingle instance = declaredConstructor.newInstance();
System.out.println(EnumSingle.INSTANCE);
System.out.println(instance);
}
}
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/a74a26f7d0fa87165569a38106a0a847.png)
为什么枚举类型可以防止反射破坏?
反编译后发现类的修饰abstract,不能创建实例,反射也无能为力