资讯 小学 初中 高中 语言 会计职称 学历提升 法考 计算机考试 医护考试 建工考试 教育百科
栏目分类:
子分类:
返回
空麓网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
空麓网 > 计算机考试 > 软件开发 > 后端开发 > Java

第五章 破坏单例模式

Java 更新时间: 发布时间: 计算机考试归档 最新发布

第五章 破坏单例模式

Java设计模式浅析

第一章 简单工厂模式
第二章 工厂方法模式
第三章 抽象工厂模式
第四章 单例模式
第五章 破坏单例模式


文章目录
  • Java设计模式浅析
  • 一、反射破坏单例
      • 示例代码
      • 测试代码
        • 注释结果
        • 非注释结果
  • 二、序列化破坏单例
        • 示例代码
        • 测试代码
        • 注释结果
        • 非注释结果
  • 总结

一、反射破坏单例
上一章中单例模式的构造方法除了加上 private 关键字,没有做任何处理。
如果我们使用反射来调用其构造方法,在调用 getInstance() 方法,
应该有两个不同的实例。现在来看一段测试代码,以 LazyInnerClassSingleton 为例:
示例代码

LazyInnerClassSingleton

public class LazyInnerClassSingleton {
    private LazyInnerClassSingleton() {
        
    }

    // 注意关键字final,保证方法不被重写和重载
    public static final LazyInnerClassSingleton getInstance() {
        // 在返回结果之前,会先加载内部类
        // 调用内部类属性
        return LazyHolder.INSTANCE;
    }

    // 默认不加载
    //LazyHolder  单例持有者
    // 最终返回 LazyHolder 的属性 LAZY 的引用,最终把引用返回到客户端
    private static class LazyHolder {
        private static final LazyInnerClassSingleton INSTANCE = new LazyInnerClassSingleton();
    }
}

 
测试代码

LazyInnerClassSingletonTest

public class LazyInnerClassSingletonTest {
    public static void main(String[] args) {
        
        try {
            // 声明一个Class对象 该对象是LazyInnerClassSingleton
            Class clazz = LazyInnerClassSingleton.class;
            // 通过反射获取私有的构造方法
            Constructor c = clazz.getDeclaredConstructor(new Class[]{});
            // 强制访问  --private 私有成员变量 设置强制访问
            c.setAccessible(true);
            // 暴力初始化
            Object o1 = c.newInstance();
            // 调用了两次构造方法,相当于“new”了两次
            Object o2 = c.newInstance();
            System.out.println(o1 == o2);
            //System.out.println(o1);


        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
注释结果

非注释结果

二、序列化破坏单例
一个单例对象创建好后,有时候需要将对象序列化然后写入磁盘,
下次使用时再从磁盘中读取对象并进行反序列化,将其转化为内存对象。
反序列化后的对象会重新分配内存,即重新创建。如果序列化的目标对象为单例对象,
就违背了单例模式的初衷,相当于破坏了单例,来看一段代码:
示例代码

SeriableSingleton

public class SeriableSingleton implements Serializable {
    // 序列化就是把内存中的状态通过转换成字节码的形式
    // 从而转换一个 I/O 流,写入其他地方(可以是磁盘、网络 I/O)
    // 内存中的状态会永久保存下来

    // 反序列化就是将已经持久化的字节码内容转换为I/O流
    // 通过I/O流的读取,进而将读取的内容转换为Java对象
    // 在转换过程中会重新创建对象new
    private SeriableSingleton(){}
    private static final SeriableSingleton instance = new SeriableSingleton();
    public static SeriableSingleton getInstance(){
        return instance;
    }
      //避免序列化破坏单例
   
}

测试代码

SeriableSingletonTest

import java.io.*;


public class SeriableSingletonTest {
    public static void main(String[] args) {
        SeriableSingleton s1 = null;
        SeriableSingleton s2 = SeriableSingleton.getInstance();

        FileOutputStream fos = null;
        try {
            //文件输出流
            fos = new FileOutputStream("SeriableSingleton.obj");
            //对象输出流
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            //写对象
            oos.writeObject(s2);
            oos.flush();
            oos.close();

            FileInputStream fis = new FileInputStream("SeriableSingleton.obj");
            ObjectInputStream ois= new ObjectInputStream(fis);
            s1 = (SeriableSingleton) ois.readObject();
            ois.close();
            fis.close();

            System.out.println(s1 == s2);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
注释结果

非注释结果


//避免序列化破坏单例

readResolve 详解见
https://www.yuque.com/yinjianwei/vyrvkf/uxggg3#lqkFI

总结
反射会创了多个实例,最后经过判断没有返回新的实例,创建多个实例但是并没有使用。
转载请注明:文章转载自 http://www.konglu.com/
本文地址:http://www.konglu.com/it/991880.html
免责声明:

我们致力于保护作者版权,注重分享,被刊用文章【第五章 破坏单例模式】因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理,本文部分文字与图片资源来自于网络,转载此文是出于传递更多信息之目的,若有来源标注错误或侵犯了您的合法权益,请立即通知我们,情况属实,我们会第一时间予以删除,并同时向您表示歉意,谢谢!

我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2023 成都空麓科技有限公司

ICP备案号:蜀ICP备2023000828号-2