设计模式之破环单例模式和阻止破坏
目录
- 1. 序列化和反序列化
- 2. 反射
这里单例模式就不多说了
23种设计模式之单例模式
1. 序列化和反序列化
这里用饿汉式来做例子
LazySingleton
import java.io.Serializable;public class LazySingleton implements Serializable {private static LazySingleton lazySingleton = null;private LazySingleton() {}public static synchronized LazySingleton getInstance() {if (lazySingleton == null) {lazySingleton = new LazySingleton();}return lazySingleton;}
}
TestSerializer
import java.io.*;public class TestSerializer {public static void main(String[] args) throws IOException, ClassNotFoundException {// 懒汉式LazySingleton instance = LazySingleton.getInstance();// 通过序列化和反序列化的方式,创建对象ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton"));oos.writeObject(instance);ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("singleton")));LazySingleton objInstance = (LazySingleton)ois.readObject();System.out.println(instance);System.out.println(objInstance);}
}
输出结果:
yxz.singleton.LazySingleton@3764951d
yxz.singleton.LazySingleton@312b1dae
可以看到这俩对象不一样。
但是使用枚举输出结果是一样的。
如果不让其破坏呢???
我们在单例中添加一个方法。
import java.io.Serializable;public class LazySingleton implements Serializable {private static LazySingleton lazySingleton = null;private LazySingleton() {}public static synchronized LazySingleton getInstance() {if (lazySingleton == null) {lazySingleton = new LazySingleton();}return lazySingleton;}private Object readResolve() {return lazySingleton;}
}
输出结果:
yxz.singleton.LazySingleton@3764951d
yxz.singleton.LazySingleton@3764951d
这样输出结果是一样的了。因为反序列化创建对象时,是通过反射创建的,反射会调用我们自己的readResolve
方法,如果重写,会调用这个,否则会破坏单例模式。
2. 反射
通过字节码对象创建构造器对象,通过构造器对象,初始化单例对象,由于单例对象的构造方法是私有化的,调用构造器中的方法,赋予权限,创建单例对象。
TestReflect
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;public class TestReflect {public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {Class clz = LazySingleton.class;// 通过字节码对象创建构造器对象Constructor constructor = clz.getDeclaredConstructor();// 赋予权限constructor.setAccessible(true);// 初始化单例对象LazySingleton clzInstance = (LazySingleton)constructor.newInstance();System.out.println(clzInstance);LazySingleton instance = LazySingleton.getInstance();System.out.println(instance);}
}
输出结果:
yxz.singleton.LazySingleton@1b6d3586
yxz.singleton.LazySingleton@4554617c
坏了,又是一样的,这可怎么办!!!
我们如何阻止呢?
我们对代码的构造模式进行修改
import java.io.Serializable;public class LazySingleton implements Serializable {private static LazySingleton lazySingleton = null;private LazySingleton() {if(lazySingleton != null){throw new RuntimeException("不允许创建多个实例");}}public static synchronized LazySingleton getInstance() {if (lazySingleton == null) {lazySingleton = new LazySingleton();}return lazySingleton;}private Object readResolve() {return lazySingleton;}
}
这样我们再运行,输出结果是:
yxz.singleton.LazySingleton@1b6d3586
yxz.singleton.LazySingleton@4554617c
恭喜你,仍然能出现两个!!!但是,我们先创建一个对象,再使用反射呢?
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;public class TestReflect {public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {LazySingleton instance = LazySingleton.getInstance();System.out.println(instance);Class clz = LazySingleton.class;Constructor constructor = clz.getDeclaredConstructor();constructor.setAccessible(true);LazySingleton clzInstance = (LazySingleton)constructor.newInstance();System.out.println(clzInstance);}
}
运行结果:
yxz.singleton.LazySingleton@1b6d3586
Exception in thread "main" java.lang.reflect.InvocationTargetExceptionat sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)at java.lang.reflect.Constructor.newInstance(Constructor.java:423)at yxz.singleton.broker.TestReflect.main(TestReflect.java:16)
Caused by: java.lang.RuntimeException: 不允许创建多个实例at yxz.singleton.LazySingleton.<init>(LazySingleton.java:10)... 5 more
这才没有创建多个。
当然,我建议是使用枚举来组织它,不过,我在使用的时候,还是没怎怎么故意使用反射或者序列化这些来破坏单例模式。
相关文章:

设计模式之破环单例模式和阻止破坏
目录 1. 序列化和反序列化2. 反射 这里单例模式就不多说了 23种设计模式之单例模式 1. 序列化和反序列化 这里用饿汉式来做例子 LazySingleton import java.io.Serializable;public class LazySingleton implements Serializable {private static LazySingleton lazySinglet…...

11.19c++面向对象+单例模式
编写如下类: class File{ FILE* fp }; 1:构造函数,打开一个指定的文件 2:write函数 向文件中写入数据 3:read函数,从文件中读取数据,以string类型返回 代码实现: #include <iostream>using namespace std;class…...

一文了解TensorFlow是什么
TensorFlow是一个开源的机器学习框架,由Google开发并维护。它提供了一个灵活且高效的环境,用于构建和训练各种机器学习模型。 TensorFlow的基本概念包括: 张量(Tensor):TensorFlow中的核心数据结构&#x…...

如何做好一份技术文档?
打造出色技术文档的艺术 在当今技术驱动的世界中,技术文档扮演着至关重要的角色。它不仅是工程师和开发人员之间交流的桥梁,更是产品和技术成功的隐形推手。一份优秀的技术文档宛如一张精准的航海图,能够引导读者穿越技术的迷雾,…...

Linux和Ubuntu的关系
Linux和Ubuntu的关系: 1. Linux本身是内核,Ubuntu系统是基于Linux内核的操作系统。 2. Linux内核操作系统的构成: 内核、shell、文件系统、应用程序 -应用程序:文本编辑器等 -文件系统:文件存放在存储设备上的组织方…...

软件工程之静态建模
静态模型:有助于设计包、类名、属性和方法特征标记(但不是方法体)的定义,例如UML类图。 用例的关系: 扩展关系: 扩展关系允许一个用例(可选)扩展另一个用例(基用例&…...

PICO VR串流调试Unity程序
在平时写Unity的VR程序的时候,需要调试自己写的代码,但是有的时候会发现场景过于复杂,不是HMD一体机能运行的,或者为了能够更方便的调试,不需要每次都将程序部署到眼睛里,这样非常浪费时间,对于…...

自媒体图文视频自动生成软件|03| 页面和结构介绍
代码获取方式在文本末尾🔚 *代码获取方式在文本末尾🔚 *代码获取方式在文本末尾🔚 *代码获取方式在文本末尾🔚 视频图片生成器 一个基于 Python 和 Web 的工具,用于生成带有文字和语音的视频以及图片。支持多种尺寸、…...

深入浅出摸透AIGC文生图产品SD(Stable Diffusion)
hihi,朋友们,时隔半年(24年11月),终于能腾出时间唠一唠SD了🤣,真怕再不唠一唠,就轮不到SD了,技术更新换代是在是太快! 朋友们,最近(24年2月)是真的没时间整理笔记,每天都在疯狂的学习Stable Diffusion和WebUI & ComfyUI,工作实在有点忙,实践期间在飞书上…...

解析生成对抗网络(GAN):原理与应用
目录 一、引言 二、生成对抗网络原理 (一)基本架构 (二)训练过程 三、生成对抗网络的应用 (一)图像生成 无条件图像生成: (二)数据增强 (三ÿ…...

CodeIgniter URL结构
CodeIgniter 的URL 结构设计得简洁且易于管理。通常遵循以下模式: http://<domain>/<index_page>/<controller>/<method>/<parameters> 下面是每个部分的详细说明: <domain>: 这是你的网站域名&#…...

从 App Search 到 Elasticsearch — 挖掘搜索的未来
作者:来自 Elastic Nick Chow App Search 将在 9.0 版本中停用,但 Elasticsearch 拥有你构建强大的 AI 搜索体验所需的一切。以下是你需要了解的内容。 生成式人工智能的最新进展正在改变用户行为,激励开发人员创造更具活力、更直观、更引人入…...

鸿蒙本地模拟器 模拟TCP服务端的过程
鸿蒙模拟器模拟TCP服务端的过程涉及几个关键步骤,主要包括创建TCPSocketServer实例、绑定IP地址和端口、监听连接请求、接收和发送数据以及处理连接事件。以下是详细的模拟过程: **1.创建TCPSocketServer实例:**首先,需要导入鸿蒙…...

Qt/C++基于重力模拟的像素点水平堆叠效果
本文将深入解析一个基于 Qt/C 的像素点模拟程序。程序通过 重力作用,将随机分布的像素点下落并水平堆叠,同时支持窗口动态拉伸后重新计算像素点分布。 程序功能概述 随机生成像素点:程序在初始化时随机生成一定数量的像素点,每个…...

Zookeeper学习心得
本人学zookeeper时按照此文路线学的 Zookeeper学习大纲 - 似懂非懂视为不懂 - 博客园 一、Zookeeper安装 ZooKeeper 入门教程 - Java陈序员 - 博客园 Docker安装Zookeeper教程(超详细)_docker 安装zk-CSDN博客 二、 zookeeper的数据模型 ZooKeepe…...

嵌入式开发工程师面试题 - 2024/11/24
原文嵌入式开发工程师面试题 - 2024/11/24 转载请注明来源 1.若有以下定义语句double a[8],*pa;int i5;对数组元素错误的引用是? A *a B a[5] C *(p1) D p[8] 解析: 在 C 或 C 语言中&am…...

Python中打印当前目录文件树的脚本
效果图: 实现脚本: 1、显示所有文件和文件夹: import osdef list_files(startpath, prefix):items os.listdir(startpath)items.sort()for index, item in enumerate(items):item_path os.path.join(startpath, item)is_last index le…...

全景图像(Panorama Image)向透视图像(Perspective Image)的跨视图转化(Cross-view)
一、概念讲解 全景图像到透视图像的转化是一个复杂的图像处理过程,它涉及到将一个360度的全景图像转换为一个具有透视效果的图像,这种图像更接近于人眼观察世界的方式。全景图像通常是一个矩形图像,它通过将球面图像映射到平面上得到…...

Redis 中的 hcan 命令耗内存,有什么优化的方式吗 ?
Redis 中的 hcan 命令耗内存,有什么优化的方式吗 ? 1. 使用合适的游标值:2. 控制每次迭代返回的键数量:3. 避免长时间运行的迭代:4. 使用HSCAN与SCAN命令结合:5. 优化哈希表结构:6. 监控和调整R…...

豆包MarsCode算法题:三数之和问题
问题描述 思路分析 1. 排序数组 目的: 将数组 arr 按升序排序,这样可以方便地使用双指针找到满足条件的三元组,同时避免重复的三元组被重复计算。优势: 数组有序后,处理两个数和 target - arr[i] 的问题可以通过双指针快速找到所有可能的组…...

【Android】AnimationDrawable帧动画的实现
目录 引言 一、AnimationDrawable常用方法 1.1 导包 1.2 addFrame 1.3 setOneShot 1.4 start 1.5 stop 1.6 isRunning 二、 从xml文件获取并播放帧动画 2.1 创建XML文件 2.2 在布局文件中使用帧动画资源 三、在代码中生成并播放帧动画 3.1 addFrame加入帧动画列…...

【消息序列】详解(7):剖析回环模式--设备测试的核心利器
目录 一、概述 1.1. 本地回环模式 1.2. 远程环回模式 二、本地回环模式(Local Loopback mode) 2.1. 步骤 1:主机进入本地环回模式 2.2. 本地回环测试 2.2.1. 步骤 2a:主机发送HCI数据包并接收环回数据 2.2.2. 步骤 2b&…...

解决Ubuntu 22.04系统中网络Ping问题的方法
在Ubuntu 22.04系统中,网络问题时有发生,尤其是当涉及到静态IP地址配置和网线直连的两台机器时。本文将探讨一种常见问题——断开并重新连接网线后,尽管网卡显示为UP状态,但无法立即ping通对方机器,以及如何解决这一问…...

【大数据学习 | Spark-SQL】Spark-SQL编程
上面的是SparkSQL的API操作。 1. 将RDD转化为DataFrame对象 DataFrame: DataFrame是一种以RDD为基础的分布式数据集,类似于传统数据库中的二维表格。带有schema元信息,即DataFrame所表示的二维表数据集的每一列都带有名称和类型。这样的数…...

15分钟做完一个小程序,腾讯这个工具有点东西
我记得很久之前,我们都在讲什么低代码/无代码平台,这个概念很久了,但是,一直没有很好的落地,整体的效果也不算好。 自从去年 ChatGPT 这类大模型大火以来,各大科技公司也都推出了很多 AI 代码助手ÿ…...

manim动画编程(安装+入门)
文章目录 1.基本介绍2.效果展示3.安装步骤3.1安装manba软件3.2配置环境变量3.3查看是否成功3.4什么是mamba3.5创建虚拟环境3.6尝试进入虚拟环境 4.vscode操作4.1默认配置文件 5.安装ffmpeg6.安装manim软件6.vscode制作7.我的学习收获 1.基本介绍 这个manim就是一款软件&#x…...

STL算法之数值算法<stl_numeric.h>
这一节介绍的算法,统称为数值(numeric)算法。STL规定,欲使用它们,客户端必须包含头文件<numeric>.SGI将它们实现与<stl_numeric.h>文件中。 目录 运用实例 accumulate adjacent_difference inner_product partial_sum pow…...

Oracle如何记录登录用户IP
在运维场景中,在定位到某个SQL引起系统故障之后,想知道是哪台机器发过来的,方便定位源头,该如何解决? 在 Oracle 数据库中记录登录用户的 IP 地址可以通过多种方法实现。以下是几种常见的方法,包括使用触发…...

Python图像处理:打造平滑液化效果动画
液化动画中的强度变化是通过在每一帧中逐渐调整液化效果的强度参数来实现的。在提供的代码示例中,强度变化是通过一个简单的线性插值方法来控制的,即随着动画帧数的增加,液化效果的强度也逐渐增加。 def liquify_image(image, center, radius…...

构建Ceph分布式文件共享系统:手动部署指南
#作者:西门吹雪 文章目录 micro-Services-TutorialCeph分布式文件共享方案部署Ceph集群使用CephCeph在kubernetes集群中的使用 micro-Services-Tutorial 微服务最早由Martin Fowler与James Lewis于2014年共同提出,微服务架构风格是一种使用一套小服务来开发单个应…...