110.【十万字带你深入学习23种设计模式】(七)

简介: 110.【十万字带你深入学习23种设计模式】
  1. 反射 (破坏单列模式)

静态内部类

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();
    }
}

我们先进行写入数据、然后再读取数据~

  1. 反射方式破解单列地解决办法
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("你好");
    }
}

相关文章
|
7月前
|
设计模式 监控 安全
多线程设计模式【多线程上下文设计模式、Guarded Suspension 设计模式、 Latch 设计模式】(二)-全面详解(学习总结---从入门到深化)
多线程设计模式【多线程上下文设计模式、Guarded Suspension 设计模式、 Latch 设计模式】(二)-全面详解(学习总结---从入门到深化)
123 0
|
6月前
|
设计模式 存储 算法
设计模式学习心得之五种创建者模式(2)
设计模式学习心得之五种创建者模式(2)
53 2
|
6月前
|
设计模式 uml
设计模式学习心得之前置知识 UML图看法与六大原则(下)
设计模式学习心得之前置知识 UML图看法与六大原则(下)
49 2
|
6月前
|
设计模式 安全 Java
设计模式学习心得之五种创建者模式(1)
设计模式学习心得之五种创建者模式(1)
44 0
|
6月前
|
设计模式 数据可视化 程序员
设计模式学习心得之前置知识 UML图看法与六大原则(上)
设计模式学习心得之前置知识 UML图看法与六大原则(上)
50 0
|
7月前
|
设计模式 安全 Java
【JAVA学习之路 | 基础篇】单例设计模式
【JAVA学习之路 | 基础篇】单例设计模式
|
7月前
|
设计模式 安全 Java
【设计模式学习】单例模式和工厂模式
【设计模式学习】单例模式和工厂模式
|
7月前
|
设计模式 算法 程序员
Python从入门到精通:2.1.3深入学习面向对象编程——设计模式的学习与实践
Python从入门到精通:2.1.3深入学习面向对象编程——设计模式的学习与实践
|
7月前
|
设计模式 存储 前端开发
JS的几种设计模式,Web前端基础三剑客学习知识分享,前端零基础开发
JS的几种设计模式,Web前端基础三剑客学习知识分享,前端零基础开发
|
7月前
|
设计模式 存储 前端开发
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式