设计模式.创建型设计模式.单例设计模式

单例设计模式

单例设计模式的代码用例:

D:\Java\_DesignPattern\DesignPattern\_1_CreatePatterns\SingletonPattern\demo

单例模式是java中最简单的设计模式之一,这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方法。

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

即每次创建的同一个类的对象都一样

  • 单例模式的主要有以下角色:
    1. 单例类,只能创建一个实例的类
    2. 访问类,使用单例类

单例模式的实现

  • 饿汉式:类加载就会导致该单实例对象被创建(特点是浪费内存)(比如在静态代码块创建对象,或者定义一个该类的静态属性)

  • 懒汉式:类加载不会导致该单实例对象被创建,而是首次使用该对象时才会创建(可以在类中的方法中创建对象)

  • 懒汉式加载的双重检查锁模式是一种非常好的单例实现模式。解决了单例、性能、线程安全问题,双重检查所模式看上去很完美,其实存在问题:在多线程的情况下可能出现空指针问题,出现问题原因是JVM在实例化对象的时候会进行优化和指令重排序操作,要解决双重检查锁模式带来指针异常的问题,只需要使用volatile关键字,volatile关键字可以保证可见性和有序性。保证了在多线程情况下线程安全也不会由性能问题

image-20230919100514942

  • 懒汉式加载(静态内部类方式)

静态内部类单例模式中实例由内部类创建,由于JVM在加载外部类的过程中,是不会加载静态内部类的,只有内部类的属性/方法被调用时才会被加载,并初始化其静态属性,静态属性由于被static修饰,保证只能被实例化一次,并且严格保证实例化顺序。

image-20230919101838058

  • 关于静态内部类方式的说明

    • 第一次加载Demo5类时不会去初始化INSTANCE , 只有第一次调用getInstance(),虚拟机加载Demo5Holder并初始化INSTANCE,这样不仅能确保线程安全,也能保证Demo5类的唯一性。
    • 静态内部类单例模式是一种优秀的单例模式,是开源项目中比较常用的一种单例模式,在没有任何锁的情况下,保证了多线程下的安全,并且没有任何性能影响和空间的浪费。
  • 枚举方式(属于饿汉式方式)【在不考虑浪费空间的情况下首选枚举方式】

枚举类实现单例模式是极力推荐的单例设计模式,因为枚举类型是线程安全的,并且只会装载一次,设计者充分的利用了枚举这个特性来实现单例模式,枚举的写法非常简单,而且枚举类型是所用单例实现中唯一一种不会被破坏的单例设计模式。

image-20230919103743347

image-20230919103818859

单例设计模式存在的问题

  • 破坏单例模式:
    • 使上面定义的单例类可以创建多个对象,枚举方式除外(枚举方式实现的单例设计模式不会被破坏)有两种方式,分别是序列化和反射。

序列化反序列化破坏单例模式

image-20230919110139499

  • 解决方案

在类中添加readSolve方法,在序列化时被反射调用,如果定义了这个方法,就返回这个方法的返回值,反之没有定义该放大,就返回新new出来的对象

image-20230919113417684

反射破坏单例模式

image-20230919111721056

  • 解决方案

  • 下面的图片最后的 ) 没有加,因为之前的网络不行,没上传到图床,有网环境后重新上传到图床↓

![image-20230919163609166](C:\Users\王东林的计算机\AppData\Roaming\Typora\typora-user-images\image-20230919163609166.png

image-20230919115651982

源码分析

  • JDK源码中的Runtime类使用的就是单例设计模式

点咖啡案例

D:\Java\_DesignPattern\DesignPattern\_1_CreatePatterns\SingletonPattern\demo\src\main\java\com\example\SingleTonCase

  • 该案例的单例模式实现方式是懒汉式
posted @ 2023-09-25 18:21  hobbit_donglin  阅读(12)  评论(0)    收藏  举报