设计模式之(4)——单例模式

定义:单例模式属于创建型模式,该类负责创建自己的对象实例,并且确保只有单个对象被创建,同时该类提供了一种全局访问其唯一实例对象的方式;这个定义中有三个要点:1、单例类只能有一个实例;2、单例类必须自己创建自己的唯一实例;3、单例类必须可以给其他所有对象提供这一唯一实例;

意图:保证一个类仅有一个实例,并提供一个访问它的全局节点;

主要解决:一个全局使用的对象的频繁地创建和销毁;

何时使用:想控制类的数目,节省系统资源的时候;

如何解决:判断系统是否已经有这个实例,有则直接返回,没有则创建返回;

关键代码:构造函数私有;

应用实例:

1、一个班级只有一个班主任;

2、Windows是多进程多线程的操作系统,在操作一个文件的时候,就不可避免地出现多个线程或者多个进程同时操作一个文件的现象,所有的文件处理必须通过一个唯一的实例来进行处理;

优点:

1、内存中只有相关对象的一个实例,减少了内存开销,尤其是频繁地创建和销毁的实例;

2、避免了对资源的多重占用;

缺点:

1、没有接口,不能继承,与单一职责冲突,一个类应该只关心内部逻辑,而不应该关系外部怎么来实例化它;

使用场景:

1、要求生产唯一序列号;

2、WEB中的计数器,不用每次刷新都在数据库中更新一次,用单例先缓存起来;

3、创建一个对象需要消耗过多的系统资源的时候,比如I/O和数据库连接等等;

单例模式的几种常见写法:

以上的四种写法大部分精力都在致力于保证多线程并发下的线程安全;因为构造方法都是私有的,也可以避免由反射获取对象实例( 在未开启忽略权限检查的情况下);但是还没有解决由于序列化和反序列化导致获取的不是同一个实例的问题,那么怎么解决呢?

答案是:在单例类中增加一个readResolve()方法,返回这个唯一的实例,就可以解决这个问题啦,这是因为反序列化的readObject()底层会做个判断,假如当前反序列化的目标对象有ReadResolve()方法,那么会调用目标类的这个方法返回一个实例对象。

最后一种单例写法,通过枚举来实现单例,这种比较推荐,这种写法天然就是线程安全的,所以我们就不需要花费大量的精力来保证线程安全,同时既可以防止反序列化生成不同实例,又可以防止反射生成不同实例:

为什么既可以避免反射生成不同实例,又可以避免反序列化生成不同实例呢?下面我们一一道来:

1、至于为什么通过反射不能生成实例对象呢?请看下这个枚举类反编译之后的代码,同时还包含一个匿名内部类:

仔细分析这个枚举反编译之后的代码,枚举类的enum其实是个关键字,普通的枚举类其实都是一个继承了Enum的普通的java子类,所有的枚举类都具有这个公共的父类,列子中的枚举类也包含了两个静态属性SPRING和ENUM$VALUES,这两个静态属性的初始化是在静态块中进行的,类加载执行静态块中的代码时候会初始化给这两个静态属性赋值,而类加载的过程会调用ClassLoader类的loadClass()方法,这个方法的方法体是用synchronized修饰的,必定是线程安全的,所以我们说这种写法是线程安全的原因在这,并且这两个静态属性还是final修饰的,一旦初始化完成则不允许修改,初始化完成之后我们的SPRING =new Singleton(“SPRING”, 0),又因为我们这个枚举类中包含了抽象方法,根据java规范,抽象方法只能存在于接口或者抽象方法中,所以这个子类反编译之后必然是用abstract修饰的抽象类,众所周知抽象类是不能被实例化的,并且这两个类中没有定义无参构造方法,所以不能被反射实例化了。

2、为什么能防止反序列化生成多个对象呢(当然我们说序列化的前提是类都实现了序列化接口)?

首先要从枚举类的序列化说起,枚举类在序列化的时候其实只是将Singleton(key,value)中的key进行了序列化,而反序列化的时候也是通过这个key去对应的map中获取对应的Singleton(key,value)实例的,大致就是这么个逻辑,有兴趣可以翻翻源码看看。

Original: https://www.cnblogs.com/wha6239/p/16635112.html
Author: 一只烤鸭朝北走
Title: 设计模式之(4)——单例模式

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/612882/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 【Kubernetes系列】Kubernetes组件介绍

    文章目录 概述 Control Plane(控制面) * etcd(分布式的键值对数据存储系统) kube-apiserver(API服务器) kube-scheduler(调度器…

    数据库 2023年6月6日
    096
  • 数据库概述

    MySQL的启动、停止 启动: net start mysql80 停止: net stop mysql80 (PS:mysql80为Win注册到MySQL中的系统服务名称)* M…

    数据库 2023年6月16日
    0112
  • 设计模式之(3)——抽象工厂方法模式

    定义:抽象工厂模式简单地讲,就是提供一个超级工厂,围绕这个超级工厂创建其他工厂;抽象工厂模式提供一个创建一些列相关或者相互依赖对象的接口; 在此之前我们先来讲一下产品等级和产品族的…

    数据库 2023年6月14日
    067
  • leetcode 226. Invert Binary Tree 翻转二叉树(简单)

    一、题目大意 给你一棵二叉树的根节点 root ,翻转这棵二叉树,并返回其根节点。 示例 1: 输入:root = [4,2,7,1,3,6,9]输出:[4,7,2,9,6,3,1…

    数据库 2023年6月16日
    070
  • 记一次vcenter连接esxi失败问题排查(443端口不通)

    vecenter错误 esxi宿主机重启后,vcenter连接esxi提示超时,使用vmware客户端连接esxi也提示超时,开始介入排查。 故障排查 如何进入命令终端 运行alt…

    数据库 2023年6月9日
    0101
  • ATM系统开发(Java版)

    ATM系统Java模拟开发总结 ATM系统开发 技术点分析 1.面向对象编程 每个用户的账户都是一个对象,所以需要设计账户类Accent用于创建账户对象封装账户信息。 2.使用集合…

    数据库 2023年6月16日
    064
  • 实时流计算—数据采集工具Flume

    Flume最早是Cloudera提供的一个高可用的,高可靠的,分布式的海量日志采集、聚合和传输的系统。 Flume特性 1.提供上下文路由特征 2.Flume的管道是基于事务,保证…

    数据库 2023年6月6日
    0256
  • Go语言常见的并发模式

    Go语言常见的并发模式 并发不是并行 并发关注的是程序的设计层面,并发的程序也可以顺序执行,在多核CPU上才可能真正同时的运行,并行关注的是程序的运行层面,如GPU中对图像处理都会…

    数据库 2023年6月16日
    066
  • 【转】Windows安装运行Kafka

    一、安装JAVA JDK 1、下载安装包 注意:根据32/64位操作系统下载对应的安装包 2、添加系统变量:JAVA_HOME=C:\Program Files (x86)\Jav…

    数据库 2023年6月6日
    060
  • SQL Server中STATISTICS IO物理读和逻辑读的误区

    SQL Server中STATISTICS IO物理读和逻辑读的误区 大家知道,SQL Server中可以利用下面命令查看某个语句读写IO的情况 SET STATISTICS IO…

    数据库 2023年6月9日
    070
  • SQL的约束

    概念:约束是作用于表中的字段以限制表中数据存储的规则 [En] concept: constraints are rules that act on fields in a tab…

    数据库 2023年5月24日
    091
  • 面试现场!月薪3w+的这些数据挖掘SQL面试题你都掌握了吗? ⛵

    💡 作者:韩信子@ShowMeAI📘 数据分析实战系列:https://www.showmeai.tech/tutorials/40📘 AI 面试题库系列:https://www….

    数据库 2023年5月24日
    090
  • Redis-实现分布式锁

    单节点分布式锁 本地的锁操作非常常见,无非就是申请一个锁变量lock, 加锁时,判断锁变量是否被持有,如果被持有中,则加锁失败,如果不被持有,则加锁成功,将锁的状态改为持有锁的这个…

    数据库 2023年6月11日
    063
  • mysql中generated always as的使用

    — generated always as的使用CREATE TABLE t1(c1 INT,c2 DOUBLE(20,19) ,c3 INT GENERATED AL…

    数据库 2023年6月9日
    083
  • 使用Typora + 阿里云OSS + PicGo 打造个人图床

    使用Typora + 阿里云OSS + PicGo 打造个人图床 为什么要打造图床? 让笔记远走高飞 试问以下场景: 我们要 markdown 笔记放到某博客上,直接进行复制即可。…

    数据库 2023年6月9日
    089
  • MRCTF2020 pyFlag

    可以看到在zip文件头和jpg文件尾中有提示这是秘密文件的part1,那么思路就打开了,将其他图片的秘密文件部分拼成一个文件即可。 全部合起来组成一个zip文件,不是伪加密,先爆破…

    数据库 2023年6月11日
    067
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球