前言

本片博客主要记录Java23种设计模式中的创建型模式中的单例模式。单例模式可分为两类,一种是饿汉式,一种是懒汉式。饿汉式的三种设计方式(静态变量方式、静态代码块方式、枚举方式),懒汉式(单锁检查方式、双锁检查方式、静态内部类方式),以及破坏单例模式的两种方式:序列化反序列化,反射。

设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性

单例模式结构

私有的构造方法【核心】

私有的、静态的实例化变量应用

提供一个公有的、静态的获取类实例对象方法

单例模式

单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。它提供了一种创建对象的最佳方式。

单例模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

1、单例类只能有一个实例。

2、单例类必须自己创建自己的唯一实例。

3、单例类必须给所有其他对象提供这一实例。

饿汉式

静态变量方式
  • 直接在创建对象时赋值
package hello;

public class Hello {

    public static void main(String[] args) {
//只能通过getSingleton方法获取,不能通过new方法创建
Singleton singleton = Singleton.getSingleton();
Singleton singleton11 = Singleton.getSingleton(); //通过hashCode查看是否是同一个对象
System.out.println(singleton.hashCode());
System.out.println(singleton11.hashCode()); }
} class Singleton{ //私有构造方法,这样外界就不能创建了
private Singleton(){
} //自己创建一个对象
private static Singleton singleton = new Singleton(); //给外界提供一个方法用于访问
public static Singleton getSingleton(){
return singleton;
} }
静态代码块方式
  • 在静态代码块里赋值
package hello;

public class Hello {

    public static void main(String[] args) {
//只能通过getSingleton方法获取,不能通过new方法创建
Singleton singleton = Singleton.getSingleton();
Singleton singleton11 = Singleton.getSingleton(); //通过hashCode查看是否是同一个对象
System.out.println(singleton.hashCode());
System.out.println(singleton11.hashCode()); }
} class Singleton{ //私有构造方法,这样外界就不能创建了
private Singleton(){
} //自己创建一个对象,但是不实例
private static Singleton singleton; //通过静态代码块赋值
static {
singleton = new Singleton();
} //给外界提供一个方法用于访问
public static Singleton getSingleton(){
return singleton;
} }
枚举方式

由于上面检测代码相同,就不在这里重复复制了。

只需要把class Singleton改为下面就行了

enum Singleton{
SINGLETON;
}

懒汉式

单锁检查模式
package hello;

public class Hello {

    public static void main(String[] args) {

        Singleton singleton = Singleton.getSingleton();
Singleton singleton11 = Singleton.getSingleton(); //通过hashCode查看是否是同一个对象
System.out.println(singleton.hashCode());
System.out.println(singleton11.hashCode()); }
} class Singleton{ //私有构造方法,这样外界就不能创建了
private Singleton(){ } //自己声明一个对象
private static Singleton singleton; //给外界提供一个方法用于访问
public static synchronized Singleton getSingleton(){
//判读singleton是否为null,如果是null就创建,否者直接返回
if (singleton == null){
singleton = new Singleton();
}
return singleton;
} }
双重检查锁模式

上面的验证都是一样的,这里只显示Singleton类就行

class Singleton{

    //私有构造方法,这样外界就不能创建了
private Singleton(){ } //自己声明一个对象
private static volatile Singleton singleton; //给外界提供一个方法用于访问
public static synchronized Singleton getSingleton(){
//判读singleton是否为null,如果是null就创建,否者直接返回
if (singleton == null){
synchronized (Singleton.class){
if (singleton == null){
singleton = new Singleton();
}
}
}
return singleton;
} }

静态内部类实现

  • 静态内部类单例模式是一种优秀的单例模式,是比较常用的单例模式。在没有加任何锁时保证线程安全,并且没有任何性能影响和空间浪费。

  • 在加载Singleton时不会初始化singleton,只有第一次调用getSingleton()时。JVM加载SingletonHolder初始化singleton。

class Singleton{

    //私有构造方法,这样外界就不能创建了
private Singleton(){ } //定义一个静态内部类
private static class SingletonHolder{
//只会初始化一次
private static final Singleton singleton= new Singleton();
}
//给外界提供一个方法用于访问
public static synchronized Singleton getSingleton(){
return SingletonHolder.singleton;
} }

破坏单例模式

  • 破坏单例模式的方式有两种一种是序列化反序列化,另一种是反射,这里我们指记录反射
  • 道高一尺,魔高一丈。有模式就会有破坏,有破坏还会有防破坏,但是还有反反破坏。这里面就多了。

通过反射破坏单例模式

package hello;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; public class Hello { public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException { //获取Singleton字节码对象
Class<Singleton> singletonClass = Singleton.class;
//获取无参构造方法
Constructor<Singleton> declaredConstructor = singletonClass.getDeclaredConstructor();
//取消访问检查
declaredConstructor.setAccessible(true);
//创建Singleton对象
Singleton singleton = (Singleton) declaredConstructor.newInstance();
Singleton singleton1 = (Singleton) declaredConstructor.newInstance();
//通过hashCode查看是否是同一个对象
System.out.println(singleton.hashCode());
System.out.println(singleton1.hashCode());
}
} class Singleton{ //私有构造方法,这样外界就不能创建了
private Singleton(){ } //定义一个静态内部类
private static class SingletonHolder{
//只会初始化一次
private static final Singleton singleton= new Singleton();
}
//给外界提供一个方法用于访问
public static synchronized Singleton getSingleton(){
return SingletonHolder.singleton;
} }

单例模式优缺点

优点:

  • 单例模式在内存中只有一个实例,减少内存开支,特别是一个对象需要频繁地创建销毁时,而且创建或销毁时性能又无法优化,单例模式就非常明显了
  • 单例模式只生成一个实例,减少系统的性能开销
  • 单例模式可以避免对资源的多重占用
  • 单例模式可以在系统设置全局的访问点,优化和共享资源访问

    缺点:
  • 不适用于变化的对象
  • 由于单例模式没有抽象层,所以扩展困难
  • 单例类的职责过重,在一定程度上违背了“单一职责原则”
  • 单一职责原则:一个类,应该只有一个职责

Java设计模式之单例模式理解的更多相关文章

  1. 折腾Java设计模式之单例模式

    博文原址:折腾Java设计模式之单例模式 单例模式 Ensure a class has only one instance, and provide a global point of access ...

  2. java 设计模式之单例模式

    -------Success is getting what you want, happiness is wanting what you get. java设计模式之单例模式(Singleton) ...

  3. Java设计模式之单例模式(七种写法)

    Java设计模式之单例模式(七种写法) 第一种,懒汉式,lazy初始化,线程不安全,多线程中无法工作: public class Singleton { private static Singleto ...

  4. Java 设计模式之单例模式(一)

    原文地址:Java 设计模式之单例模式(一) 博客地址:http://www.extlight.com 一.背景 没有太多原由,纯粹是记录和总结自己从业以来经历和学习的点点滴滴. 本篇内容为 Java ...

  5. java设计模式1——单例模式

    java设计模式1--单例模式 1.单例模式介绍 1.1.核心作用:保证一个类只有一个实例,并且提供一个访问该实例的全局访问点 1.2.常见场景 1.3.单例模式的优点 1.4.常见的五种单例模式实现 ...

  6. java设计模式之单例模式你真的会了吗?(懒汉式篇)

    java设计模式之单例模式你真的会了吗?(懒汉式篇) 一.什么是单例模式? 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供 ...

  7. java设计模式之单例模式(几种写法及比较)

    概念: Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例.饿汉式单例.登记式单例. 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建 ...

  8. [转]JAVA设计模式之单例模式

    原文地址:http://blog.csdn.net/jason0539/article/details/23297037 概念: java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主 ...

  9. java设计模式之三单例模式(Singleton)

    单例对象(Singleton)是一种常用的设计模式.在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在.这样的模式有几个好处: 1.某些类创建比较频繁,对于一些大型的对象,这是一笔 ...

随机推荐

  1. [源码解析] NVIDIA HugeCTR,GPU 版本参数服务器 --(1)

    [源码解析] NVIDIA HugeCTR,GPU版本参数服务器 --(1) 目录 [源码解析] NVIDIA HugeCTR,GPU版本参数服务器 --(1) 0x00 摘要 0x01 背景 1.1 ...

  2. Redis 源码简洁剖析 12 - 一条命令的处理过程

    命令的处理过程 Redis server 和一个客户端建立连接后,会在事件驱动框架中注册可读事件--客户端的命令请求.命令处理对应 4 个阶段: 命令读取:对应 readQueryFromClient ...

  3. Solution -「洛谷 P4194」矩阵

    \(\mathcal{Description}\)   Link.   给定一个 \(n\times m\) 的矩阵 \(A\),构造一个 \(n\times m\) 的矩阵 \(B\),s.t. \ ...

  4. 我们一起来学grep

    文章目录 grep 介绍 grep 命令格式 grep 命令选项 grep 实例 查找指定进程 查找指定进程个数 从文件中读取关键词进行搜索 从多个文件中查找关键字 输出以u开头的行 输出非u开头的行 ...

  5. MLHPC 2016 | Communication Quantization for Data-parallel Training of Deep Neural Networks

    本文主要研究HPC上进行数据并行训练的可行性.作者首先在HPC上实现了两种通信量化算法(1 Bit SGD以及阈值量化),然后提出了自适应量化算法以解决它们的缺点.此外,发挥出量化算法的性能,作者还自 ...

  6. TCP/IP详解 读书笔记:TCP:传输控制协议

    TCP的服务 TCP为应用层提供一种面向连接的.可靠的字节流服务. 一个TCP连接中,仅有两方进行彼此通信,所以广播和多播不能用于TCP. TCP通过以下方式提供可靠性: 应用数据被切割为TCP认为最 ...

  7. windbg调试系列教程:sos扩展的介绍和使用

    SOS是什么? 直观来说,sos就是一个程序集文件.这个程序集的作用就是让我们在使用windbg分析.net进程时,更加方便快捷.通过sos,我们可以清晰的查看CLR运行时的各类信息,辅助我们去理解托 ...

  8. 2022李宏毅作业hw1—新冠阳性人员数量预测。

    ​ 事前  : kaggle地址:ML2021Spring-hw1 | Kaggle 我的git地址: https://github.com/xiaolilaoli/lihongyi2022homew ...

  9. Clickhouse - Replication机制

    Clickhouse - Replication机制 1. Replication引擎族 Replication仅对于MergeTree引擎族提供支持, 两者是正交的: ReplicatedMerge ...

  10. 【C# .Net GC】手动监视和控制对象的生命周期(GCHandle)

    这个话题还未做详细研究,暂时用不到,只是粗略看了一下. 使用System.Runtime.InteropServices.GCHandle类来手动控制对象的生命周期 (个人感觉这里可能有一些问题... ...