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

news2024/9/21 22:44:37

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

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

设计模式目录

  • 一. 🦁 设计模式🌟知道
    • 1. 创建型模式:
    • 2. 结构型模式:
    • 3. 行为型模式:
  • 二. 🦁 目标掌握🌟单例模式
    • Ⅰ. 懒汉模式
    • Ⅱ. 饿汉模式
    • Ⅲ. 静态内部类
    • Ⅳ. 枚举类型
    • Ⅴ. 使用场景
  • 三. 🦁 学习总结🌟

一. 🦁 设计模式🌟知道

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种设计模式之一的单例模式,小伙伴们一起干起来叭!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/506480.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Postman安装及入门接口测试使用步骤

前言 在软件测试行业中,作为一款比jemter更便捷更好用的软件测试工具,postman以其便捷灵活性首当其冲,成为当今测试行业领域使用较广泛的主流系统软件接口测试工具。今天Darren洋为大家讲解postman这款软件测试工具的下载安装及入门接口测试步…

Sentinel实现动态配置的集群流控的方法

Sentinel实现动态配置的集群流控的方法 介绍 06-cluster-embedded-8081 为什么要使用集群流控呢? 相对于单机流控而言,我们给每台机器设置单机限流阈值,在理想情况下整个集群的限流阈值为机器数量✖️单机阈值。不过实际情况下流量到每台…

拉绳位移传感器连接到PLC并采集数据到物联网云平台

拉绳位移传感器是一种利用绳材收卷轮周长来计量物体长度或距离的传感器设备,其作用就像是一把卷尺,通过拉绳的长度变化测出位移量,并转换为数字量提供到电子信息系统中,在建筑、水利、地质勘察、采矿、制造加工以及渔业等广泛应用…

elementUI中折叠面板箭头图标位置调整到最左边

跟flex布局有关 原始代码 <div id"app"> <el-collapse v-model"activeNames" change"handleChange"><el-collapse-item title"一致性 Consistency" name"1"><div>与现实生活一致&#xff1a;与现…

Centos8下编译安装最新版ffmpeg解决方案(含Centos8换源阿里云)

文章目录 1、下载FFmpeg源代码2、安装依赖3、配置编译选项&#xff08;关键&#xff09;linux依赖手动编译安装centos8换源阿里云 4、编译源代码5、安装FFmpeg6、验证安装 1、下载FFmpeg源代码 FFmpeg官网&#xff08;https://ffmpeg.org/download.html&#xff09;git clone …

python数据分析案例——天猫订单综合分析

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 什么是数据分析 明确目的–获得数据(爬虫&#xff0c;现有&#xff0c;公开的数据)–数据预处理——数据可视化——结论 准备 环境使用&#xff1a; 在开始写我们的代码之前&#xff0c;我们要准备好运行代码的程序 Anacon…

Java Stream API的基本使用方法

前言 Java各个版本所更新的主要内容&#xff1a; 1.Java SE 8&#xff1a;引入了一些新特性&#xff0c;如lambda表达式、Stream API、格式化日期、国际化等。此外&#xff0c;还对并发编程进行了改进&#xff0c;引入了线程安全的Stream API。 2.Java SE 9&#xff1a;新增了…

李沐论文精度系列之十:GPT-4

文章目录 一、AIGC资讯速览1.1 Toolformer&#xff08;2023.2.9&#xff09;1.2 ChatGPT plugin1.3 LLaMA&#xff08;2023.2.24&#xff09;1.4 Visual ChatGPT&#xff08;2023.3.8&#xff09;1.5 GigaGAN&#xff08;2023.3.9&#xff09;1.6 Stanford Alpaca&#xff08;2…

面试官:详细说一下Java语言层面3种IO模型的实现

在Java中&#xff0c;一共有三种IO模型&#xff0c;分别是阻塞IO(BIO)、非阻塞IO(NIO)和异步IO(AIO)。 Linux五种IO模型和Java三种IO模型 Java BIO Java BIO就是Java的传统IO模型&#xff0c;对应了操作系统IO模型里的阻塞IO。 Java BIO相关的实现都位于java.io包下&#xf…

ECMA 各版本特性汇总

&#xff08;走运时,要想到倒霉&#xff0c;不要得意得过了头&#xff1b;倒霉时,要想到走运&#xff0c;不必垂头丧气。心态始终保持平衡&#xff0c;情绪始终保持稳定&#xff0c;此亦长寿之道。。——季羡林&#xff09; ECMA ecma官方网站 ecma github版本记录 w3schools …

由浅入深,聊聊OkHttp的那些事(易懂,不繁琐)

作者&#xff1a;Petterp 引言 在 Android 开发的世界中&#xff0c;有一些组件&#xff0c;无论应用层技术再怎么迭代&#xff0c;作为基础支持&#xff0c;它们依然在那里。 比如当我们提到网络库时&#xff0c;总会下意识想到一个名字&#xff0c;即 OkHttp 。 尽管对于大…

LVS和nginx和keepalived四层和7层的一些测试,nginx和keepalived共用环境的部署,lvs,nginx客户端IP透传

LVS和nginx的测试 实验DR模式 服务器IP备注mysql192.168.137.178测试服务器lvs**vip ** 192.168.137.99 RIP 192.168.137.100lvs服务器nginx1RIP 192.168.137.101nginx2RIP 192.168.137.102 LVS四层代理 test----lvs vip—nginx1/ngin2 LVS服务器的配置 [rootlvs openres…

Databend 开源周报第 92 期

Databend 是一款现代云数仓。专为弹性和高效设计&#xff0c;为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务&#xff1a;https://app.databend.cn 。 Whats On In Databend 探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。 在 WHERE 子句中…

算法记录 | Day56 动态规划

583.两个字符串的删除操作 思路&#xff1a; 1.确定dp数组&#xff08;dp table&#xff09;以及下标的含义&#xff1a;dp[i][j]&#xff1a;以i-1为结尾的字符串word1&#xff0c;和以j-1位结尾的字符串word2&#xff0c;想要达到相等&#xff0c;所需要删除元素的最少次数…

别去外包,干了3年,彻底废了......

先说一下自己的情况。大专生&#xff0c;19年通过校招进入湖南某软件公司&#xff0c;干了接近3年的测试&#xff0c;今年年上旬&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落&#xff01;而我已经在一个企业干了三年&#xff0c…

存储迁移到vSAN后将oracle rac的共享虚拟磁盘由“精简置备”转换为“厚置备快速置零”格式

在vSAN 6.5.0环境中&#xff0c;将Oracle RAC虚拟机的存储迁移到vSAN数据存储后&#xff0c;共享磁盘在迁移后全部变成了“精简置备”类型&#xff0c;如下所示&#xff1a; 注&#xff1a;从vSAN 6.7 Patch 01开始&#xff0c;vSAN上的Oracle RAC 不再要求共享的 VMDKs为厚置…

【论文阅读】COPA:验证针对中毒攻击的离线强化学习的稳健策略

COPA: Certifying Robust Policies for Offline Reinforcement Learning against Poisoning Attacks 作者&#xff1a;Fan Wu, Linyi Li, Chejian Xu 发表会议&#xff1a;2022ICRL 摘要 目前强化学习完成任务的水平已经和人类相接近&#xff0c;因此研究人员的目光开始转向…

Springboot Security 认证鉴权——使用JSON格式参数登录

在 Spring Security 中&#xff0c;默认的登陆方式是以表单形式进行提交参数的。可以参考前面的几篇文章&#xff0c;但是在前后端分离的项目&#xff0c;前后端都是以 JSON 形式交互的。一般不会使用表单形式提交参数。所以&#xff0c;在 Spring Security 中如果要使用 JSON …

Ansys Lumerical | 单行载流子光电探测器仿真方法

综述 在本例中&#xff0c;我们将研究混合硅基光电探测器的各项性能。单行载流子&#xff08;uni-traveling carrier&#xff0c;UTC&#xff09;光电探测器&#xff08;PD&#xff09;由InP/InGaAs制成&#xff0c;其通过渐变耦合的方式与硅波导相连。在本次仿真中&#xff0c…

04-Docker镜像

镜像 镜像是一种轻量级、可执行的独立软件包&#xff0c;它包含运行某个软件所需的所有内容&#xff0c;我们把应用程序和配置依赖打包好形成一个可交付的运行环境&#xff08;包括代码、运行时需要的库、环境变量和配置文件等&#xff09;&#xff0c;这个打包好的运行环境就是…