【设计模式】| 修炼内功 | 23种设计模式——单例模式

命运对每个人都是一样的,不一样的是各自的努力和付出不同,付出的越多,努力的越多,得到的回报也越多,在你累的时候请看一下身边比你成功却还比你更努力的人,这样,你就会更有动力。

导读:本篇文章讲解 【设计模式】| 修炼内功 | 23种设计模式——单例模式,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

设计模式如同织锦之艺术,精心构筑,展示优美。
学习设计模式,犹如追逐清晨的曙光,扉页掀开了人生的新篇章。当你学会设计模式的奥秘,就如同走进了灯火通明的城市,丰富多彩的建筑,让你大开眼界,拥有了整个世界般的视野。
设计模式如同一面明镜,让人自省和反思,看清自己的不足;同时也是一盏明灯,照亮你前行的道路。
它像是一座桥,将你从学生的世界带入到职业的殿堂,让你稳步前行。
学习设计模式,让你的代码更有灵魂,更有温度,更有品味。
它是一种成长,是一种提升,更是一种追求卓越的态度。
让我们一起学习设计模式,饱览编程之美!

快来和🦁一起学习设计模式叭,修炼内功无上心法!!!
在这里插入图片描述

一. 🦁 设计模式🌟知道

23种设计模式可以按照其功能划分为三类,分别是创建型模式、结构型模式和行为型模式,具体如下:

1. 创建型模式:

  • 工厂方法模式(Factory Method)
  • 抽象工厂模式(Abstract Factory)
  • 单例模式(Singleton)
  • 建造者模式(Builder)
  • 原型模式(Prototype)

2. 结构型模式:

  • 适配器模式(Adapter)
  • 桥接模式(Bridge)
  • 组合模式(Composite)
  • 装饰器模式(Decorator)
  • 外观模式(Facade)
  • 享元模式(Flyweight)
  • 代理模式(Proxy)

3. 行为型模式:

  • 职责链模式(Chain of Responsibility)
  • 命令模式(Command)
  • 解释器模式(Interpreter)
  • 迭代器模式(Iterator)
  • 中介者模式(Mediator)
  • 备忘录模式(Memento)
  • 观察者模式(Observer)
  • 状态模式(State)
  • 策略模式(Strategy)
  • 模板方法模式(Template Method)
  • 访问者模式(Visitor)

以上23种设计模式都是经典的设计模式,它们被广泛应用于软件开发中,以提高代码的可复用性、扩展性、灵活性和可维护性。
今天我们先来研究一下单例模式

二. 🦁 目标掌握🌟单例模式

Ⅰ. 懒汉模式

延迟加载,只有在真正使用的时候,才开始实例化

  1. 线程安全问题

  2. double check 加锁优化

  3. 编译器(JIT),CPU 有可能对指令进行重排序,导致使用到尚未初始化的实例,可以通过添加volatile 关键字进行修饰对于volatile 修饰的字段,可以防止指令重排

class LazySingleton{
    //  加volatile 防止多线程情况下,CPU 有可能对指令进行重排序
    private volatile static LazySingleton instance;
    private LazySingleton(){}
    public  static LazySingleton getInstance(){
        if (instance == null){
            synchronized (LazySingleton.class){
                if (instance == null){
                    instance = new LazySingleton();
                }
            }
        }
        return instance;
    }

}

这样输出的实例都会是同一个,如图:

image-20230423104901755

Ⅱ. 饿汉模式

类加载的 初始化阶段就完成了 实例的初始化 。本质上就是借助于JVM类加载机制,保证实例的唯一性。

类加载过程:

  1. 加载二进制数据到内存中,生成对应的Class数据结构

  2. 连接: a.验证,b.准备 (给类的静态成员变量赋默认值),c.解析

  3. 初始化: 给类的静态变量赋初值

class HungarySingleton{
    private static HungarySingleton instance = new HungarySingleton();
//    使用私有构造函数,防止从外部实例化实例。
    private HungarySingleton (){};
    public static   HungarySingleton getInstance(){
        return instance;
    }

}

只有在真正使用对应的类时,才会触发初始化 如(当前类是启动类即main函数所在类,直接进行new 操作,访问静态属性、访问静态方 法,用反射访问类,初始化一个类的子类等.)

image-20230423112544508

Ⅲ. 静态内部类

静态内部类模式将单例对象的创建和getInstance()方法的调用分开,只有在第一次调用getInstance()方法时,才会触发静态内部类的加载,进而创建单例对象。由于一个类的静态内部类只会被加载一次,因此静态内部类模式也是线程安全的。

  1. 本质上是利用类的加载机制来保证线程安全
  2. 只有在实际使用的时候,才会触发类的初始化,所以也是懒加载的一种形式
public class InnerClassSingletonTest {
    public static void main(String[] args) {
        new Thread(()->{
            InnerClassSingleton instance = InnerClassSingleton.getInstance();
            System.out.println(instance);
        }
        ).start();
        new Thread(()->{
            InnerClassSingleton instance = InnerClassSingleton.getInstance();
            System.out.println(instance);
        }
        ).start();

    }

}
// 静态内部类模式
class InnerClassSingleton{
    private static class InnerClassSingleHolder{
        private static InnerClassSingleton instance = new InnerClassSingleton();
    }
    private InnerClassSingleton(){}
    public static InnerClassSingleton getInstance(){
        return InnerClassSingleHolder.instance;
    }
}

即使是在多线程模式下,获取的也是同一个实例,运行结果如下:

image-20230423113006567

Ⅳ. 枚举类型

是一种利用枚举类型实现的单例模式,它可以保证在任何情况下都只有一个实例对象存在。枚举类型在Java中天生是单例的,所以枚举实现的单例模式非常简单,同时也具有线程安全、防止反射和序列化攻击的特点。但是,它不太灵活,不能继承其他类或者实现接口。

public enum EnumSingleton {
    INSTANCE;

    public static EnumSingleton getInstance() {
        return INSTANCE;
    }
}

Ⅴ. 使用场景

  • 要求生成唯一序列号的环境;

  • 在整个项目中需要一个共享访问点或共享数据,例如一个Web页面上的计数器,可以不用把每次刷新都记录到数据库中,使用单例模式保持计数器的值,并确保是线程安全的;

  • 创建一个对象需要消耗的资源过多,如要访问IO和数据库等资源;

  • 需要定义大量的静态常量和静态方法(如工具类)的环境,可以采用单例模式(当然,也可以直接声明为static的方式)。

三. 🦁 学习总结🌟

本文分享了23种设计模式之一的单例模式,小伙伴们一起干起来叭!!!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/143123.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!