当前位置: 首页 > news >正文

探索单例模式:设计模式中的瑰宝

文章目录

  • 常用的设计模式有以下几种:
    • 一.创建型模式(Creational Patterns):
    • 二.结构型模式(Structural Patterns):
    • 三.行为型模式(Behavioral Patterns):
    • 四.并发模式(Concurrent Patterns):
  • 单例模式概念
  • 一、懒汉式(Lazy Initialization)示例:
  • 二、饿汉式(Eager Initialization)示例:
  • 三、静态内部类示例(推荐使用):
  • 四、枚举示例(推荐使用):
  • 总结


常用的设计模式有以下几种:

一.创建型模式(Creational Patterns):

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

二.结构型模式(Structural Patterns):

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

三.行为型模式(Behavioral Patterns):

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

四.并发模式(Concurrent Patterns):

单例模式(Singleton Pattern,在多线程环境下的应用)
生成器模式(Builder Pattern,在多线程环境下的应用)
保护性暂停模式(Guarded Suspension Pattern)
观察者模式(Observer Pattern,在多线程环境下的应用)

这些设计模式涵盖了对象的创建、对象间的组织和交互、以及对象的行为等方面,可以帮助开发者更好地组织和设计代码,提高代码的可扩展性、可维护性以及重用性。需要根据实际情况选择适合的设计模式来解决问题。


单例模式概念

单例模式是设计模式中的一种,旨在确保一个类只有一个实例对象,并提供全局访问点来获取该实例。

单例模式的关键要点如下😊😊😊:

1.私有构造函数:为了防止外部直接创建实例,将类的构造函数设为私有。

2.静态方法或静态变量:提供一个静态方法或静态变量来获取类的唯一实例。

3.延迟实例化或饿汉式初始化:根据需要可以选择延迟实例化或在类加载时就进行初始化。

4.线程安全性:需考虑在多线程环境下保证单例对象的创建和访问的线程安全性。

5.全局访问点:提供一个全局访问点,使得任何地方都可以获取到单例实例。

同时,单例模式也有一些注意点,如可能引起全局状态的问题、对单元测试的影响等,需要权衡利弊来选择适合的使用场景。😎😎😎
在这里插入图片描述

单例模式有以下几种常见的实现方法:😊😊😊

1.懒汉式(Lazy Initialization):

在第一次使用时才创建实例。
线程不安全,需要考虑多线程环境下的同步问题。
可以通过双重检查锁定、同步方法等方式来实现线程安全。

2.饿汉式(Eager Initialization):

在类加载时就创建实例。
线程安全,因为实例在类加载时就已经创建。
可能会导致不必要的资源浪费,因为实例在整个程序运行期间都存在,即使不使用也会被创建。

3.静态内部类:

使用静态内部类来持有单例实例,在第一次使用时才创建实例。
线程安全,因为静态内部类在类加载时只会被加载一次,保证了实例的唯一性。
推荐使用这种方式实现单例,因为代码简洁、线程安全,且支持懒加载。

4.枚举:

枚举常量就是单例对象的实例。
线程安全,且支持序列化和反序列化,以及防止反射攻击。
推荐使用这种方式实现单例,因为代码简洁、线程安全,且具有额外的优势。

一、懒汉式(Lazy Initialization)示例:

以下是一个懒汉式实现单例模式的示例(非线程安全版本):

public class LazySingleton {private static LazySingleton instance;private LazySingleton() {// 私有的构造函数,防止外部实例化}public static LazySingleton getInstance() {if (instance == null) {instance = new LazySingleton();}return instance;}// 其他方法...
}

在这个示例中,LazySingleton类的构造函数是私有的,不允许外部直接实例化对象。getInstance()方法是懒汉式的获取单例实例的方法。在第一次调用getInstance()时,会创建一个新的实例对象并将其赋值给instance变量。之后的调用都会返回之前创建的实例对象。

需要注意的是,这个示例是非线程安全的版本,多线程环境下可能会出现竞态条件。如果多个线程同时调用getInstance()方法,并且instance还没有被初始化,那么可能会创建多个实例。为了解决这个问题,可以使用同步机制(如双重检查锁定)来确保线程安全性。

下面是一个线程安全的双重检查锁定的示例:

public class LazySingleton {private static volatile LazySingleton instance;private LazySingleton() {// 私有的构造函数,防止外部实例化}public static LazySingleton getInstance() {if (instance == null) {synchronized (LazySingleton.class) {if (instance == null) {instance = new LazySingleton();}}}return instance;}// 其他方法...
}

在这个示例中,使用了双重检查锁定来确保线程安全。通过在synchronized块内进行二次判断,可以在多线程环境下保证只有一个实例被创建。

需要注意的是,上述示例虽然解决了线程安全性问题,但在某些情况下(如高并发场景)性能可能会有一定的影响。因此,在实际使用中可以根据需求权衡利弊来选择合适的实现方式。

二、饿汉式(Eager Initialization)示例:

以下是一个饿汉式实现单例模式的示例:

public class EagerSingleton {private static final EagerSingleton instance = new EagerSingleton();private EagerSingleton() {// 私有的构造函数,防止外部实例化}public static EagerSingleton getInstance() {return instance;}// 其他方法...
}

在这个示例中,EagerSingleton类在类加载时就创建了一个实例对象,并将其赋值给静态final的instance变量。getInstance()方法直接返回该实例,因此在任何时候调用getInstance()都会获取到同一个实例对象。

饿汉式的实现方式是在类加载时就进行实例化,因此可以保证线程安全性。由于实例在整个程序运行期间都会存在,可能会导致不必要的资源浪费。另外,需要注意的是,在某些特殊情况下可能会引起类加载的顺序问题,需要注意类加载的先后顺序。

总结来说,饿汉式是一种简单、线程安全的单例模式实现方式,适用于实例始终需要被创建且资源消耗较小的情况。但需要注意在某些特殊情况下可能引发的顺序问题。

三、静态内部类示例(推荐使用):

public class Singleton {private Singleton() {// 私有的构造函数,防止外部实例化}private static class SingletonHolder {private static final Singleton instance = new Singleton();}public static Singleton getInstance() {return SingletonHolder.instance;}// 其他方法...
}

在这个示例中,Singleton类的实例被定义为私有的静态内部类SingletonHolder的静态成员变量。通过使用静态内部类的方式,可以实现懒加载和线程安全,而无需使用显式的同步机制。

四、枚举示例(推荐使用):

使用枚举实现单例具有以下优点:

线程安全:枚举常量的创建是线程安全的,不会被多个线程重复创建。

防止序列化和反射攻击:枚举类默认实现了Serializable接口,使用枚举实现的单例对象在序列化和反序列化时会得到正确的结果。同时,由于枚举常量有固定的实例,不会受到反射攻击。

以下是使用枚举实现单例的示例:

public enum Singleton {INSTANCE;public void doSomething() {// 单例对象的方法}
}

在这个示例中,Singleton是一个枚举类型,并且定义了一个名为INSTANCE的枚举常量,它是单例对象的唯一实例。可以通过Singleton.INSTANCE来访问这个单例对象,并调用其方法。

使用枚举实现单例模式简洁且安全,不需要担心线程安全和反射攻击的问题。因此,当需要实现单例时,可以优先考虑使用枚举来实现。

总结

单例模式的应用有很多,例如全局资源管理、日志记录器、数据库连接池、配置管理器等。
它可以简化代码,提高资源的利用效率,并确保全局只有一个实例对象。😎😎😎

@作者:加辣椒了吗?
简介:憨批大学生一枚,喜欢在博客上记录自己的学习心得,也希望能够帮助到你们!
在这里插入图片描述

相关文章:

探索单例模式:设计模式中的瑰宝

文章目录 常用的设计模式有以下几种:一.创建型模式(Creational Patterns):二.结构型模式(Structural Patterns):三.行为型模式(Behavioral Patterns):四.并发…...

Bobo String Construction 2023牛客暑期多校训练营4-A

登录—专业IT笔试面试备考平台_牛客网 题目大意&#xff1a;给出一字符串t&#xff0c;求一个长为n的字符串&#xff0c;使tst中包含且仅包含两个t 1<n<1000;测试样例组数<1000 思路&#xff1a;一开始很容易想到如果t里有1&#xff0c;s就全0&#xff0c;否则s就全…...

【React学习】React父子组件通讯

1. 父到子传值 在React框架中&#xff0c;父组件可以通过 props 将数据传递给子组件。子组件通过读取 props 来访问父组件传递过来的数据。 当父组件的 props 发生变化时&#xff0c;React 会自动重新渲染子组件以确保子组件中使用的数据保持同步。 父组件 import React, {…...

NASM汇编

1. 前置知识 1. 汇编语言两种风格 intel&#xff1a;我们学的NASM就属于Intel风格AT&T&#xff1a;GCC后端工具默认使用这种风格&#xff0c;当然我们也可以加选项改成intel风格 2. 代码 1. 段分布 .text: 存放的是二进制机器码&#xff0c;只读.data: 存放有初始化的…...

第三章 HL7 架构和可用工具 - 使用 HL7 架构结构页面

文章目录 第三章 HL7 架构和可用工具 - 使用 HL7 架构结构页面使用 HL7 架构结构页面查看文档类型列表查看消息结构查看段结构 第三章 HL7 架构和可用工具 - 使用 HL7 架构结构页面 使用 HL7 架构结构页面 通过 HL7 架构页面&#xff0c;可以导入和查看 HL7 版本 2 架构规范。…...

spring注解驱动开发(一)

1、需要导入的spring框架的依赖 <dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>4.3.12.RELEASE</version></dependency>2、Configuration 设置类为配置类 3、Annota…...

Vue3搭建启动

Vue3搭建&启动 一、创建项目二、启动项目三、配置项目1、添加编辑器配置文件2、配置别名3、处理sass/scss4、处理tsx(不用的话可以不处理) 四、添加Eslint 一、创建项目 npm create vite 1.project-name 输入项目名vue3-vite 2.select a framework 选择框架 3.select a var…...

阻塞队列(模拟实现)

概念 阻塞队列是带有阻塞功能的队列 特性 当队列满的时候&#xff0c;继续入队列&#xff0c;就会出现阻塞&#xff0c;阻塞到其他线程从队列中取走元素为止 当队列空的时候&#xff0c;继续出队列&#xff0c;也会发生阻塞&#xff0c;阻塞到其他线程往队列中添加元素为止 特…...

VScode中python的相对路径与绝对路径 FileNotFoundError: [Errno 2] No such file or directory

VScode中&#xff0c;python里的相对路径是相对于当前工作目录来定位的&#xff0c;而当前的工作目录在VScode中下方的终端窗口会有提示&#xff1a; 说明此时的工作目录并非当前python文件所在的目录&#xff0c;而是C:\Users\xxxxx(你的用户名)。因此&#xff0c;使用VScode…...

Unity XML2——C#读写XML

一、XML 文件的存放位置 &#xff08;一&#xff09;只读不写的 XML ​ 放在 Resouces 或者 StreamingAssets 文件夹下&#xff0c;详见 Unity基础3——Resources资源动态加载_weixin_53163894的博客-CSDN博客。 &#xff08;二&#xff09;动态存储的 XML ​ 放在 Applica…...

带wiringPi库的交叉编译 ---宿主机x86Ubuntu,目标机ARMv8 aarch64(香橙派)

带wiringPi库的交叉编译如何进行 先交叉编译wiringPi库&#xff0c;编译出的库适合香橙派&#xff0c;这时候交叉编译可执行程序的平台和链接库的格式也是正确的&#xff0c;然后通过-I和-L来指定链接的wiringPi库的头文件和库的位置&#xff0c;但是现在还没有学习过&#xf…...

数据仓库基础知识

什么是数据仓库&#xff1f; 数仓&#xff0c;DataWarehouse&#xff0c;是一个 面向主题的、集成的、稳定的、与时间相关的 数据集合。 而这个数据集合的建立&#xff0c;是为了支持管理者的决策过程。 也就是说&#xff0c;我们通过建设数仓&#xff0c;为业务中的流程改进、…...

M 芯片的 macos 系统安装虚拟机 centos7 网络配置

centos 安装之前把网络配置配好或者是把网线插好 第一步找到这个 第二步打开网络适配器 选择图中所指位置 设置好之后 开机启动 centos 第三步 开机以后 编写网卡文件保存 重启网卡就可以了&#xff0c;如果重启网卡不管用&#xff0c;则重启虚拟机即可 “ ifcfg-ens160 ” 这…...

AcWing 3708. 求矩阵的鞍点

输入样例&#xff1a; 3 4 1 2 3 4 1 2 3 4 1 2 3 4输出样例&#xff1a; 1 4 4 2 4 4 3 4 4 #include<bits/stdc.h> using namespace std; const int N1010; int n,m,a[N][N],x[N],y[N],flag1; int main(){scanf("%d%d",&n,&m);for(int i1;i<n;i…...

web前端开发工程师的具体职责范本(合集)

web前端开发工程师的具体职责范本1 职责&#xff1a; 1.负责web前端架构的搭建&#xff0c;核心业务功能开发和核心代码编写。 2.配合产品经理&#xff0c;实现产品UI和交互方面的需求&#xff0c;持续界面优化&#xff0c;提升用户体验。 3.参与相关业务需求变更评审。 4.…...

从源程序到可执行文件的四个过程

从源程序到可执行文件的四个过程 预处理编译汇编链接 程序要运行起来&#xff0c;必须要经过四个步骤&#xff1a;预处理、编译、汇编和链接&#xff0c;如下图所示&#xff1a; -E选项&#xff1a;提示编译器执行完预处理就停下来&#xff0c;后边的编译、汇编、链接就先不执…...

C++部署学习

gcc -E src/main.c -o src/main.i gcc -S src/main.c -o src/main.s gcc -C src/main.c -o src/main.o gcc src/main.c -o exec ./exec...

linux下lazarus开发ide里 BGRAControls控件库comboBox示例

下载开发工具 ftp://ftp.freepascal.org/pub/lazarus/releases/Lazarus%20Linux%20amd64%20DEB/Lazarus%202.2.6/https://sourceforge.net/projects/lazarus/files/Lazarus%20Linux%20amd64%20DEB/Lazarus%202.2.6/ sourceforge下载可能比较慢&#xff0c;选择 下载有问题&…...

Redis学习路线(9)—— Redis的场景使用

默认做好了其它的前提&#xff0c;只专注于Redis使用 一、短信登录 在没有Redis数据库时&#xff0c;我们会基于Session实现登录&#xff08;利用令牌进行授权&#xff09;&#xff0c;是怎么实现的呢&#xff1f; &#xff08;一&#xff09;基于Session的短信登录功能 1、…...

糟了,数据库主从延迟了!

前言 在实际的生产环境中&#xff0c;由单台MySQL作为独立的数据库是完全不能满足实际需求的&#xff0c;无论是在安全性&#xff0c;高可用性以及高并发等各个方面 因此&#xff0c;一般来说都是通过集群主从复制&#xff08;Master-Slave&#xff09;的方式来同步数据&…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

rnn判断string中第一次出现a的下标

# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...

tomcat入门

1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效&#xff0c;稳定&#xff0c;易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...

【LeetCode】算法详解#6 ---除自身以外数组的乘积

1.题目介绍 给定一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O…...

nnUNet V2修改网络——暴力替换网络为UNet++

更换前,要用nnUNet V2跑通所用数据集,证明nnUNet V2、数据集、运行环境等没有问题 阅读nnU-Net V2 的 U-Net结构,初步了解要修改的网络,知己知彼,修改起来才能游刃有余。 U-Net存在两个局限,一是网络的最佳深度因应用场景而异,这取决于任务的难度和可用于训练的标注数…...

若依登录用户名和密码加密

/*** 获取公钥&#xff1a;前端用来密码加密* return*/GetMapping("/getPublicKey")public RSAUtil.RSAKeyPair getPublicKey() {return RSAUtil.rsaKeyPair();}新建RSAUti.Java package com.ruoyi.common.utils;import org.apache.commons.codec.binary.Base64; im…...

Pydantic + Function Calling的结合

1、Pydantic Pydantic 是一个 Python 库&#xff0c;用于数据验证和设置管理&#xff0c;通过 Python 类型注解强制执行数据类型。它广泛用于 API 开发&#xff08;如 FastAPI&#xff09;、配置管理和数据解析&#xff0c;核心功能包括&#xff1a; 数据验证&#xff1a;通过…...

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅!

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅! 🌱 前言:一棵树的浪漫,从数组开始说起 程序员的世界里,数组是最常见的基本结构之一,几乎每种语言、每种算法都少不了它。可你有没有想过,一组看似“线性排列”的有序数组,竟然可以**“长”成一棵平衡的二…...

Java中HashMap底层原理深度解析:从数据结构到红黑树优化

一、HashMap概述与核心特性 HashMap作为Java集合框架中最常用的数据结构之一&#xff0c;是基于哈希表的Map接口非同步实现。它允许使用null键和null值&#xff08;但只能有一个null键&#xff09;&#xff0c;并且不保证映射顺序的恒久不变。与Hashtable相比&#xff0c;Hash…...