设计模式之单例实现
单例模式------即在内存中只存在该对象得一个实例
饿汉方式------即创建实例对象的时机是在类加载时:只要使用到该类就会触发private static Test Instance=new Test();此句代码运行,调用构造方法创建一个实例对象。且饿汉式没有多线程安全问题,都是以jvm保证安全的。
1.简单方式实现饿汉
public class Test implements Serializable {
//静态实例代码段,饿汉实现类加载初始化时调用构造方法
private static Test Instance=new Test();
//私有方法防止外部调用创建对象
private Test(){
System.out.println("构造方法");
}
//外部类获得单例对象方法
public static Test getInstance(){
return Instance;
}
//其他方法
public static void otherMethod(){
System.out.println("other");
}
}
该单例实现方式可以被反序列化和反射破坏,反射破坏方式如下:该方式可以通过构造方法创建出一个全新的实例对象
public static void reflect() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
System.out.println(Test.getInstance());
//反射破坏
//得到类
Class c = Test.class;
Constructor> constructor = c.getDeclaredConstructor();
//设置私有可调用
constructor.setAccessible(true);
// 打印创建的实例对象
System.out.println(constructor.newInstance());
}
可见该方法是通过调用构造方法创建出一个新的对象
反序列化破坏单例方式如下:
public static void ser() throws IOException, ClassNotFoundException {
//反序列化
ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream=new ObjectOutputStream(outputStream);
//将类转化
objectOutputStream.writeObject(Test.getInstance());
System.out.println(Test.getInstance());
ObjectInputStream objectInputStream=new ObjectInputStream(new ByteArrayInputStream(outputStream.toByteArray()));
//读出类,变为一个新的类
Test test= (Test) objectInputStream.readObject();
System.out.println(test);
}
该方式可以看出反序列化构造出的对象并不是通过构造方法!
由此针对上面两种破坏方式做出优化得到以下的代码
public class Test implements Serializable {
//静态实例代码段,饿汉实现类加载初始化时调用构造方法
private static Test Instance=new Test();
//私有方法防止外部调用创建对象
private Test(){
if(Instance!=null)// 此处方式反射调用破环单例对象,抛出异常
throw new RuntimeException("单例模式不能创建");
System.out.println("构造方法");
}
//外部类获得单例对象方法
public static Test getInstance(){
return Instance;
}
//其他方法
public static void otherMethod(){
System.out.println("other");
}
//防止反序列化破坏单例
public Object readResolve(){
return Instance;
}
}
2.枚举类实现饿汉
public enum Test_1 {
Instance;
//枚举类默认构造方法私有
Test_1(){
System.out.println("构造方法");
}
//获取对象
public static Test_1 getInstance(){
return Instance;
}
//其他方法
public static void otherMethod(){
System.out.println("other");
}
}
枚举类实现方式不会被反射和反序列化破环单例



