- 反射 (破坏单列模式)
静态内部类
package com.jsxs.pattern.singletion.demo8; /** * @Author Jsxs * @Date 2023/4/16 18:22 * @PackageName:com.jsxs.pattern.singletion.demo8 * @ClassName: Singleton * @Description: TODO 反射破坏单列模式 * @Version 1.0 */ public class Singleton { // 1.定义私有化构造函数: 不让外部类创建对象 private Singleton(){} // 2.定义静态内部类 private static class SingletonHard{ private static final Singleton instance=new Singleton(); } // 3.开发端口 public static Singleton getInstance(){ return SingletonHard.instance; } }
客户端
package com.jsxs.pattern.singletion.demo8; import java.lang.reflect.Constructor; /** * @Author Jsxs * @Date 2023/4/16 18:25 * @PackageName:com.jsxs.pattern.singletion.demo8 * @ClassName: Client * @Description: TODO * @Version 1.0 */ public class Client { public static void main(String[] args) throws Exception { // 1.获取字节码对象 Class clazz = Singleton.class; // 2.获取无参构造方法对象 Constructor cons = clazz.getDeclaredConstructor(); // 3.取消访问检查 cons.setAccessible(true); //4. 创建Singleton对象 Singleton o = (Singleton)cons.newInstance(); Singleton o2 = (Singleton)cons.newInstance(); System.out.println(o==o2); } }
破坏了单列模式
(6).解决问题-> 解决单列模式2种
1. 序列化、反序列方式破坏单列模式的解决办法
在Singleton类中添加readResolve()
方法,在序列化时被反射调用,如果定义了这个方法,就返回这个方法的值,如果没有定义,则返回新new出来的对象。
这个名字是一个固定的变量名~。假如实体类被序列化了,那么会自动地实现这个代码。
// 4. 当进行反序列化时,会自动调用该方法,将该方法的返回值直接返回 public Object readResolve() { return SingletonHard.instance; } }
序列化
package com.jsxs.pattern.singletion.demo7; import java.io.Serializable; /** * @Author Jsxs * @Date 2023/4/16 17:47 * @PackageName:com.jsxs.pattern.singletion.demo7 * @ClassName: Singleton * @Description: TODO * @Version 1.0 */ public class Singleton implements Serializable { // 1.私有构造函数 private Singleton() { } // 2.静态内部类 private static class SingletonHard { private static final Singleton instance = new Singleton(); } // 3.提供公共的对象 public static Singleton getInstance() { return SingletonHard.instance; } // 4. 当金星反序列化时,会自动调用该方法,将该方法的返回值直接返回 public Object readResolve() { return SingletonHard.instance; } }
实现类
package com.jsxs.pattern.singletion.demo7; import java.io.*; /** * @Author Jsxs * @Date 2023/4/16 17:55 * @PackageName:com.jsxs.pattern.singletion.demo7 * @ClassName: Client * @Description: TODO * @Version 1.0 */ public class Client { public static void main(String[] args) throws Exception { // writeObject2File(); ReadObjectFromFile(); ReadObjectFromFile(); } // 从文件读取数据(对象) public static void ReadObjectFromFile() throws Exception { //1. 创建对象输入流 ObjectInputStream ois = new ObjectInputStream(new FileInputStream("E:\\加速器\\a.txt")); //2. 读取对象 Singleton singleton = (Singleton) ois.readObject(); System.out.println(singleton); //3. 释放资源 ois.close(); } // 向文件中写数据 (对象) public static void writeObject2File() throws Exception { //1. 获取Singleton对象 Singleton instance = Singleton.getInstance(); // 2.创建对象输出流对象 ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("E:\\加速器\\a.txt")); // 3.写对象 oos.writeObject(instance); //4.释放资源 oos.close(); } }
我们先进行写入数据、然后再读取数据~
- 反射方式破解单列地解决办法
private static boolean flag=false; // 1.定义私有化构造函数: 不让外部类创建对象 private Singleton(){ synchronized (Singleton.class){ // 判断flag地值是否是true,如果是true,说明非第一次访问,直接跑一个异常即可。如果是false的话,说明第一次创建对象 if (flag){ throw new RuntimeException("不能创建多个对象"); } // 将flag的值设置为true flag=true; } }
反射实现
package com.jsxs.pattern.singletion.demo8; /** * @Author Jsxs * @Date 2023/4/16 18:22 * @PackageName:com.jsxs.pattern.singletion.demo8 * @ClassName: Singleton * @Description: TODO 反射破坏单列模式 * @Version 1.0 */ public class Singleton { private static boolean flag=false; // 1.定义私有化构造函数: 不让外部类创建对象 private Singleton(){ synchronized (Singleton.class){ // 判断flag地值是否是true,如果是true,说明非第一次访问,直接跑一个异常即可。如果是false的话,说明第一次创建对象 if (flag){ throw new RuntimeException("不能创建多个对象"); } // 将flag的值设置为true flag=true; } } // 2.定义静态内部类 private static class SingletonHard{ private static final Singleton instance=new Singleton(); } // 3.开发端口 public static Singleton getInstance(){ return SingletonHard.instance; } }
实现类
package com.jsxs.pattern.singletion.demo8; import java.lang.reflect.Constructor; /** * @Author Jsxs * @Date 2023/4/16 18:25 * @PackageName:com.jsxs.pattern.singletion.demo8 * @ClassName: Client * @Description: TODO * @Version 1.0 */ public class Client { public static void main(String[] args) throws Exception { // 1.获取字节码对象 Class clazz = Singleton.class; // 2.获取无参构造方法对象 Constructor cons = clazz.getDeclaredConstructor(); // 3.取消访问检查 cons.setAccessible(true); //4. 创建Singleton对象 Singleton o = (Singleton)cons.newInstance(); Singleton o2 = (Singleton)cons.newInstance(); System.out.println(o==o2); } }
(7).JDK源码解析-Runtime类
Runtime类就是i使用的单列设计模式的饿汉模式
package com.jsxs.pattern.singletion.demo9; import java.io.IOException; import java.io.InputStream; /** * @Author Jsxs * @Date 2023/4/16 21:12 * @PackageName:com.jsxs.pattern.singletion.demo9 * @ClassName: RuntomeDemo * @Description: TODO * @Version 1.0 */ public class RuntimeDemo { public static void main(String[] args) throws IOException { // 获取Runtime类的对象 Runtime runtime = Runtime.getRuntime(); // 调用runtime的方法exec Process exec = runtime.exec("ipconfig"); // 调用process对象的获取输入流的方法 InputStream inputStream = exec.getInputStream(); byte[] bytes = new byte[1024 * 1024]; int count=0; while ((count=inputStream.read())!=-1){ System.out.println(new String(bytes,0,count,"utf-8")); } System.out.println("你好"); } }