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

设计模式(结构型)-享元模式

摘要

        在软件开发的广阔领域中,随着系统规模的不断膨胀,资源的有效利用逐渐成为了一个至关重要的议题。当一个系统中存在大量相似的对象时,如何优化这些对象的管理,减少内存的占用,提升系统的整体性能,成为了开发者们亟待解决的问题。享元模式作为一种结构型设计模式,应运而生,为这一难题提供了行之有效的解决方案。

定义

        享元模式,运用共享技术有效地支持大量细粒度的对象。在这一模式中,对象的状态被清晰地划分为内部状态和外部状态。内部状态,是对象中那些可以共享的相同内容,它存储于对象内部,且不会随着环境的改变而发生变化。例如,在一个图形绘制系统中,圆形的半径、颜色等属性,对于所有同类型的圆形来说,若这些属性值相同,就可视为内部状态。而外部状态,则是那些需要外部环境来设置的、无法共享的内容,其会随着环境的变化而改变。比如,在上述图形绘制系统中,圆形在画布上的具体位置,就属于外部状态。​

        值得注意的是,外部状态和内部状态相互独立,外部状态的变化不会对内部状态产生影响。通过这种状态的划分,我们可以为相同的对象设置不同的外部状态,从而使它们呈现出不同的特征,同时共享相同的内部状态,极大地减少了对象的创建数量。​

        从本质上讲,享元模式的核心在于 “分离与共享”。它将对象的状态进行分离,区分出变化的部分(外部状态)和不变的部分(内部状态),并对不变的部分进行共享。通过这种方式,达到减少对象数量、节约内存空间的目的,使系统在处理大量细粒度对象时更加高效。

作用

节约内存空间​

        在许多实际应用场景中,系统需要创建和管理大量相似的对象。例如,在一个在线游戏中,可能存在成千上万的游戏角色,这些角色在很多方面具有相似性,如角色的基本属性(生命值、攻击力等)、技能特效等。若为每个角色都创建一个独立的对象实例,将会消耗大量的内存资源。而运用享元模式,我们可以将这些角色的共同属性(内部状态)进行共享,仅为每个角色保存其独特的属性(外部状态,如在游戏地图中的位置、当前装备等)。这样,系统中实际存在的对象数量将大幅减少,从而显著节约内存空间。​

提高系统性能​

        减少对象的创建数量不仅能够降低内存的使用,还能提升系统的性能。创建对象是一个相对耗时的操作,需要分配内存、初始化对象的属性等。当系统中存在大量对象创建需求时,频繁的对象创建操作会严重影响系统的响应速度。享元模式通过共享对象,减少了不必要的对象创建,使得系统在处理大量对象时,能够更加高效地运行,提高了系统的整体性能。​

享元工厂类的核心地位​

        享元模式的核心在于享元工厂类。享元工厂类就像是一个对象的管理者,其主要职责是提供一个用于存储享元对象的享元池。当用户需要获取某个对象时,享元工厂首先会在享元池中进行查找。如果享元池中已经存在符合要求的对象,那么工厂将直接返回该对象给用户;若享元池中不存在该对象,工厂则会创建一个新的享元对象,然后将其返回给用户,并同时将这个新增对象保存到享元池中,以便后续再次使用。通过这种方式,享元工厂类有效地实现了对象的共享和复用,极大地提高了系统资源的利用效率。

类图

角色

        在享元模式的类图中,主要包含以下几个关键角色,它们相互协作,共同实现了对象的共享和高效管理:​

  • Flyweight(享元接口):作为享元对象的抽象接口,它定义了对象需要实现的方法,并且通过这些方法来接收外部状态并对其进行处理。享元接口为具体的享元实现对象提供了统一的规范,确保不同的具体享元对象在行为上具有一致性。​

  • ConcreteFlyweight(具体的享元实现对象):具体实现 Flyweight 接口的类,它是可共享的对象。在 ConcreteFlyweight 类中,需要对享元对象的内部状态进行封装,实现接口中定义的业务逻辑。例如,在一个文字排版系统中,某个特定字体、字号的文字对象就可以作为一个具体的享元实现对象,它内部封装了字体、字号等内部状态。​

  • UnsharedConcreteFlyweight(非共享的享元实现对象):并非所有的享元对象都能够被共享,UnsharedConcreteFlyweight 就是这样的非共享对象。它通常是享元对象的组合对象,包含了一些独特的、无法共享的状态。比如,在一个复杂的图形绘制系统中,一个由多个不同形状组合而成的复杂图形对象,可能就无法作为共享的享元对象,而属于非共享的享元实现对象。​

  • FlyweightFactory(享元工厂):享元工厂类在整个享元模式中起着至关重要的作用。它主要负责创建并管理共享的享元对象,维护一个享元池来存储已经创建的享元对象。当外部系统请求一个享元对象时,享元工厂首先在享元池中查找是否存在符合要求的对象,如果存在则直接返回;若不存在,则创建一个新的享元对象,将其加入享元池后再返回给请求者。享元工厂通过这种方式,有效地实现了享元对象的共享和复用

具体实现

  • Flyweight(享元接口):在 Java 代码实现中,享元接口可以通过接口或者抽象类来定义。例如,在一个图形绘制的享元模式实现中,我们可以定义如下享元接口:

public interface Shape {​void draw(int x, int y);​
}

        这里的draw方法接收外部状态(坐标x和y),用于在特定位置绘制图形。通过定义这样的接口,具体的图形享元实现对象(如圆形、矩形等)都需要实现该接口,确保了它们在处理外部状态和绘制行为上的一致性。

  • ConcreteFlyweight(具体的享元实现对象):以圆形为例,它实现了上述Shape接口:

public class Circle implements Shape {​private String color; // 内部状态,颜色​
​public Circle(String color) {​this.color = color;​}​
​@Override​public void draw(int x, int y) {​System.out.println("绘制颜色为 " + color + " 的圆形,坐标为 (" + x + ", " + y + ")");​}​
}

        在Circle类中,color属性作为内部状态被封装在对象内部,并且在draw方法中,结合传入的外部状态(坐标x和y)进行图形的绘制操作。

  • UnsharedConcreteFlyweight(非共享的享元实现对象):假设在图形绘制系统中,存在一种特殊的组合图形,它由多个不同形状的图形组合而成,并且每个组合图形都有其独特的属性和行为,无法进行共享。我们可以定义如下非共享的享元实现对象类:

public class ComplexShape {​private List shapes = new ArrayList<>();​private String uniqueProperty; // 独特的属性​
​public ComplexShape(String uniqueProperty) {​this.uniqueProperty = uniqueProperty;​}​
​public void addShape(Shape shape) {​shapes.add(shape);​}​
​public void draw() {​System.out.println("绘制具有独特属性 " + uniqueProperty + " 的复杂图形:");​for (Shape shape : shapes) {​shape.draw(0, 0); // 简单示例,实际可能需要更复杂的坐标计算​}​}​
}

        在这个ComplexShape类中,uniqueProperty属性表示其独特的、无法共享的状态,并且它可以包含多个共享的享元对象(通过addShape方法添加),在draw方法中实现了其独特的绘制逻辑。

  • FlyweightFactory(享元工厂):以下是一个简单的享元工厂类实现:

import java.util.HashMap;​
import java.util.Map;​
​
public class ShapeFactory {​private static final Map circleMap = new HashMap<>();​
​public static Shape getCircle(String color) {​Circle circle = circleMap.get(color);​if (circle == null) {​circle = new Circle(color);​circleMap.put(color, circle);​System.out.println("创建颜色为 " + color + " 的圆形");​}​return circle;​}​
}

        在这个ShapeFactory类中,维护了一个circleMap享元池来存储已经创建的圆形对象。当外部请求获取某个颜色的圆形时,首先在享元池中查找,如果不存在则创建一个新的圆形对象并放入享元池,最后返回该圆形对象,实现了圆形对象的共享和复用。

优缺点

优点

  • 减少内存中对象数量:享元模式最显著的优点之一就是能够极大地减少内存中对象的数量。通过共享相同的内部状态,系统中只需要保存一份相同状态的对象实例,而对于不同的外部状态,通过传入不同的参数来进行区分。例如,在一个包含大量文本字符的文档处理系统中,每个字符的字体、字号等内部状态可以共享,仅需为每个字符的位置等外部状态单独存储,从而使得相同或相似对象在内存中只保存一份,有效地降低了内存的占用。​

  • 外部状态独立性:享元模式中,外部状态相对独立于内部状态,并且不会影响其内部状态。这意味着享元对象可以在不同的环境中被共享使用,因为它们的核心内部状态不会因为外部环境的变化而受到影响。例如,在一个游戏场景中,游戏角色的基本属性(如生命值、攻击力等内部状态)可以被共享,而角色在不同地图中的位置(外部状态)可以根据游戏的进行随时改变,不会对角色的基本属性产生影响,使得相同的角色享元对象可以在不同的游戏场景中复用。

缺点

  • 系统复杂度增加:引入享元模式会使系统变得更加复杂。为了实现对象状态的分离和共享,需要仔细地分析和设计,将对象的状态准确地划分为内部状态和外部状态。这一过程需要开发者具备较强的抽象思维和设计能力,同时也增加了代码的理解和维护难度。例如,在一个复杂的企业级应用系统中,对于业务对象状态的划分可能需要深入了解业务逻辑和系统架构,否则可能导致状态划分不合理,影响系统的正常运行。​

  • 运行时间变长:为了实现对象的共享,享元模式需要将享元对象的状态外部化,这就意味着在使用享元对象时,需要从外部读取这些状态信息。相比于直接访问对象内部的所有状态信息,读取外部状态的操作会增加一定的运行时间开销。特别是在对性能要求极高的场景中,这种额外的运行时间开销可能会对系统的整体性能产生一定的影响。例如,在一个对实时性要求很高的金融交易系统中,频繁读取外部状态可能会导致交易响应时间变长,影响用户体验。

使用场景

大量相同或相似对象的场景​

        当一个系统中有大量相同或相似的对象存在,并且这些对象的大量使用导致内存大量耗费时,享元模式是一个非常合适的解决方案。例如,在一个在线地图应用中,地图上可能存在成千上万的标注点,这些标注点在很多属性上(如标注点的图标样式、大小等)可能是相同的,只有其在地图上的位置不同。通过使用享元模式,将标注点的共同属性作为内部状态进行共享,仅为每个标注点保存其独特的位置信息(外部状态),可以显著减少内存的占用,提高系统的运行效率。​

对象状态可外部化的场景​

        如果对象的大部分状态可以被外部化,即这些状态可以从对象中分离出来,并在需要时通过外部环境传入对象中,那么享元模式就可以发挥作用。例如,在一个图形渲染系统中,图形的颜色、形状等属性可以作为内部状态进行共享,而图形在屏幕上的显示位置、旋转角度等属性可以作为外部状态,根据用户的操作动态地传入图形对象中。这样,通过共享内部状态,减少了对象的创建数量,同时通过灵活设置外部状态,满足了不同的显示需求。​

多次重复使用享元对象的场景​

        由于使用享元模式需要维护一个存储享元对象的享元池,这本身需要耗费一定的资源,包括内存和时间。因此,只有在多次重复使用享元对象的情况下,使用享元模式才是值得的。例如,在一个数据库连接池的实现中,数据库连接对象的创建和销毁是比较耗时的操作。通过使用享元模式,将数据库连接对象作为享元对象,维护一个连接池来存储和管理这些连接对象。当应用程序需要数据库连接时,从连接池中获取已有的连接对象,使用完毕后再放回连接池。这样,在大量的数据库操作中,通过重复使用连接对象,有效地提高了系统的性能,并且弥补了维护连接池所带来的资源开销。

使用案例

JDK 类库中的 String 类

        在 JDK 类库中,String类是使用享元模式的典型代表。当我们创建字符串对象时,如果字符串的值相同,Java 会尝试从字符串常量池中获取已经存在的字符串对象,而不是创建一个新的对象。例如:

String str1 = "hello";​
String str2 = "hello";​
System.out.println(str1 == str2); // 输出 true

        在这个例子中,str1和str2指向的是字符串常量池中的同一个对象,因为它们的值都是"hello"。通过这种方式,Java 有效地减少了字符串对象的创建数量,节约了内存空间。

Integer 类中的享元模式

        在Integer类中,也应用了享元模式。当我们通过Integer.valueOf(int i)方法获取Integer对象时,如果目标值在-128到127之间,Integer类会从缓存中获取已经存在的对象,而不是创建新的对象。例如:

Integer num1 = Integer.valueOf(10);​
Integer num2 = Integer.valueOf(10);​
System.out.println(num1 == num2); // 输出 true

        这是因为在Integer类的内部维护了一个缓存数组,用于存储-128到127之间的整数对象。当请求的整数在这个范围内时,直接从缓存中返回对应的对象,实现了对象的共享,提高了系统的性能和内存利用率。

总结

        元模式作为一种强大的结构型设计模式,在优化系统性能、减少内存占用方面具有显著的优势。尽管它增加了系统的复杂度,并且在某些场景下可能会带来一定的运行时间开销,但在合适的应用场景中,其带来的好处远远超过了这些弊端。通过深入理解享元模式的原理、结构和应用场景,开发者能够更加高效地设计和构建软件系统,使其在面对大量细粒度对象时,依然能够保持良好的性能和资源利用率。

相关文章:

设计模式(结构型)-享元模式

摘要 在软件开发的广阔领域中&#xff0c;随着系统规模的不断膨胀&#xff0c;资源的有效利用逐渐成为了一个至关重要的议题。当一个系统中存在大量相似的对象时&#xff0c;如何优化这些对象的管理&#xff0c;减少内存的占用&#xff0c;提升系统的整体性能&#xff0c;成为了…...

1.1显存

显存是显卡&#xff08;GPU&#xff09;专用的高性能内存&#xff0c;负责存储渲染所需的纹理、帧缓冲、几何数据等。其设计直接影响图形性能、分辨率和复杂场景处理能力 苹果统一内存&#xff08;Unified Memory&#xff09;、集成显卡共享内存&#xff08;Integrated Graphi…...

C# 选择文件的路径、导出文件储存路径

1、选择导入文件&#xff0c;获取其路径 C#通过这段代码将弹出一个文件选择对话框&#xff0c;允许用户选择一个文件&#xff0c;并返回所选文件的完整路径。如果用户取消了选择&#xff0c;则直接返回结束函数。 string OpenFilePath;//存储选择到的文件的完整路径OpenFileDia…...

【最后203篇系列】027 基于消息队列的处理架构

起因 之所以写这篇文章&#xff0c;主要是梳理一下进展。因为同时研究好几块内容&#xff0c;切换起来要点时间。这次也是因为协作的同事们把各自的分工都搞定了&#xff0c;瓶颈反而在我自己这里&#xff0c;哈哈。 除了帮自己思路恢复过来&#xff0c;我觉得这方法可能也有…...

多线程与Tkinter界面交互

在现代图形用户界面(GUI)应用程序中,可能会遇到需要长时间运行的任务,例如网络请求、数据处理或文件读取等。如果这些任务直接在主线程中运行,会导致GUI界面“卡顿”或“不响应”。为了保持界面流畅和响应用户操作,我们可以通过使用多线程来将这些任务移到后台运行。然而…...

【工程开发】LLMC准确高效的LLM压缩工具(一)

​【文献阅读】LLMC: Benchmarking Large Language Model Quantization with a Versatile Compression Toolkit 北航 2024年10月 摘要 大语言模型&#xff08;LLMs&#xff09;的最新进展凭借其卓越的涌现能力和推理能力&#xff0c;正推动我们迈向通用人工智能。然而&#…...

回顾CSA,CSA复习

RHCSA redhat certificate system Administrator RHCE redhat certificate engineer 回顾CSA 文件管理 创建文件&#xff1a;touch 、重定向、vim 阅读文件&#xff1a;cat看短小的文件、vim、head看文件前面部分、tail看文件的尾部内容、more、less看文档使用more和less…...

基于电子等排体的3D分子生成模型 ShEPhERD - 评测

一、背景介绍 ShEPhERD 是一个由 MIT 开发的一个 3D 相互作用感知的 ligand-based的分子生成模型&#xff0c;以 arXiv 预印本的形式发表于 2024 年&#xff0c;被ICLR2025 会议接收。文章链接&#xff1a;https://openreview.net/pdf?idKSLkFYHlYg ShEPhERD 是一种基于去噪扩…...

平凡日子里的挣扎

2025年4月13日&#xff0c;9~23℃&#xff0c;好 待办&#xff1a; 融智云考平台《物理》《物理2》~~《地理》《地理1》~~重修试卷 卫健委统考监考&#xff08;2025年4月12日早上7点半&#xff09; 冶金《物理》课程标准 冶金《物理》教案 期中教学检查——自查表材料&#xff…...

智能制造方案精读:117页MES制造执行系统解决方案【附全文阅读】

本方案围绕制造执行系统(MES)展开,阐述了智能制造相关概念及发展趋势,指出 MES 是连接 ERP 与生产现场的关键系统。介绍其在加工、装配及其他场景的应用,通过实例展示各场景下的功能、特点和实施效果,如实现生产信息可视化、产品追溯、设备监控等。还提及实施 MES 面临的…...

[推荐]AI驱动的知识图谱生成器(AI Powered Knowledge Graph Generator)

网址&#xff1a;https://github.com/robert-mcdermott/ai-knowledge-graph# 一、介绍 简介&#xff1a;以非结构化文本文档为输入&#xff0c;使用您选择的LLM以主语-谓语-宾语 (SPO) 三元组的形式提取知识&#xff0c;并将这些关系可视化为交互式知识图谱 特点&#xff1a…...

波束形成(BF)从算法仿真到工程源码实现-第七节-关于波束10个基本概念

一、波束10个基本概念 1.作用&#xff1a; 对多路麦克风信号进行合并处理&#xff0c;抑制非目标方向的干扰信号&#xff0c;增强目标方向的声音信号。 2.原理&#xff1a; 调整相位阵列的基本单元参数&#xff0c;使得某些角度的信号获得相长干涉&#xff0c;而另一些角度的…...

深度学习(第一集)

123 import torch# 创建一个需要计算梯度的张量 x1 torch.tensor([2.0], requires_gradTrue)# 定义一个简单的函数 y x^2 y x1 ** 4# 计算梯度 y.backward()print("x1.grad 的值&#xff1a;", ) # 打印 x1.grad print("x1.grad 的值&#xff1a;", x1…...

Spring 事务传播行为

在Spring框架中,事务传播行为(Transaction Propagation)定义了事务在多个方法调用之间的行为方式。理解这些传播行为对于设计可靠的事务管理策略至关重要。以下是Spring支持的七种事务传播行为及其应用场景的详细说明: 1. REQUIRED(默认) 行为:如果当前存在事务,则加入…...

搬运机器人的基本工作场景及原理

搬运机器人广泛应用于工业生产中&#xff0c;主要用于搬运、堆放、装配等工作。它通过机械手臂的运动&#xff0c;结合机器视觉技术完成各种自动化作业。 一、搬运机器人的设计原理 搬运机器人通常采用可移动门架式结构&#xff0c;手臂承载机构安装在导轨上&#xff0c;可以沿…...

Ubuntu终端中常用的快捷键整理

1. 导航与编辑 光标移动&#xff1a; Ctrl A&#xff1a;跳转到行首。 Ctrl E&#xff1a;跳转到行尾。 Alt B&#xff1a;向左移动一个单词&#xff08;或 Ctrl ←&#xff09;。 Alt F&#xff1a;向右移动一个单词&#xff08;或 Ctrl →&#xff09;。 删除操作…...

mysql安装-MySQL MGR(Group Replication)+ ProxySQL 架构

文章目录 前言一、环境规划二、安装 MySQL 8.0.36&#xff08;主库&#xff0c;CentOS 9&#xff09;2.1 添加 Yum 源2.2 安装 MySQL 8.0.362.3 初始化 三、配置主库 my.cnf&#xff08;192.168.1.101&#xff09;四、&#xff08;可选&#xff09;创建远程可访问的用户&#x…...

Opencv使用cuda实现图像处理

main.py import os import cv2 print(fOpenCV: {cv2.__version__} for python installed and working) image cv2.imread(bus.jpg) if image is None:print("无法加载图像1") print(cv2.cuda.getCudaEnabledDeviceCount()) cv2.cuda.setDevice(0) cv2.cuda.printCu…...

ubuntu 安装samba

ubuntu 版本&#xff1a;Ubuntu 24.04.2 LTS 1. 保证连网 2. 安装samba sudo apt install samba 在安装结束以后&#xff0c;我们可以使用下面的命令来查看安装&#xff1a; apt list | grep samba freeipa-client-samba/noble 4.11.1-2 amd64 ldb-tools/noble 2:2.8.0samba…...

山东大学软件学院创新项目实训开发日志(12)之将对话记录保存到数据库中

在之前的功能开发中&#xff0c;已经成功将deepseekAPI接口接入到springbootvue项目中&#xff0c;所以下一步的操作是将对话和消息记录保存到数据库中 在之前的开发日志中提到数据库建表&#xff0c;所以在此刻需要用到两个表&#xff0c;conversation表和message表&#xff…...

欢乐力扣:反转链表二

文章目录 1、题目描述2、思路 1、题目描述 反转链表二。  给你单链表的头指针 head 和两个整数 left 和 right &#xff0c;其中 left < right 。请你反转从位置 left 到位置 right 的链表节点&#xff0c;返回 反转后的链表 。 2、思路 参考官方题解&#xff0c;基本思路…...

【CS*N是狗】亲测可用!!WIN11上禁用Chrome自动更新IDM插件

现象&#xff1a;每次打开chrome后IDM会弹出提示插件版本不一致。经过排查后发现是chrome把IDM插件给更新了&#xff0c;导致IDM提示版本不匹配。经过摸索后&#xff0c;得到了可行的方案。 第一步&#xff0c;打开Chrome&#xff0c;把IDM插件卸载掉&#xff0c;然后重新安装I…...

Linux:DNS服务配置(课堂实验总结)

遇到的问题&#xff0c;都有解决方案&#xff0c;希望我的博客能为你提供一点帮助。 操作系统&#xff1a;rocky Linux 9.5 ​​一、配置DNS服务器的核心步骤​​ 步骤 1&#xff1a;安装 BIND 软件​​ ​​检查是否安装​​&#xff1a; rpm -qa | grep "^bind"…...

啥是Spring,有什么用,既然收费,如何免费创建SpringBoot项目,依赖下载不下来的解决方法,解决99%问题!

一、啥是Spring&#xff0c;为啥选择它 我们平常说的Spring指的是Spring全家桶&#xff0c;我们为什么要选择Spring&#xff0c;看看官方的话&#xff1a; 意思就是&#xff1a;用这个东西&#xff0c;又快又好又安全&#xff0c;反正就是好处全占了&#xff0c;所以我们选择它…...

【LeetCode】算法详解#4 ---合并区间

1.题目介绍 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。 1 < intervals.length < 104interval…...

安装树莓派3B+环境

目录 一、安装树莓派3B环境 1.1 格式化SD卡 1.2 环境安装与配置 1.2.1 安装Raspberry Pi 1.2.2 SSH访问树莓派 1.3 创建用户账号 二、在树莓派上用C和Python编程运行一个简单的程序 2.1 C语言程序 2.2 Python程序 三、总结 树莓派是一款功能强大的微型计算机&#xf…...

​​STM32(3.3V 系统)通过串口直接向 ATmega328P(5V 系统)发送数据​​,居然能正常通信

​​核心结论​​ 如果 ​​STM32&#xff08;3.3V 系统&#xff09;通过串口直接向 ATmega328P&#xff08;5V 系统&#xff09;发送数据​​&#xff0c;​​3.3V 的 TX 高电平可能无法被 ATmega328P 可靠识别为逻辑“1”​​&#xff01;以下是详细分析&#xff1a; ​​1.…...

Java 8中的Lambda 和 Stream (from Effective Java 第三版)

42.Lambda 优先于匿名类 在之前的做法中&#xff08;Historically&#xff09;&#xff0c;使用单个抽象方法的接口&#xff08;或很少的抽象类【只有一个抽象方法的抽象类数量比较少】&#xff09;被用作函数类型。它们的实例称为函数对象&#xff0c;代表一个函数或一种行为。…...

MIPI协议介绍

MIPI协议介绍 mipi 协议分为 CSI 和DSI,两者的区别在于 CSI用于接收sensor数据流 DSI用于连接显示屏 csi分类 csi 分为 csi2 和 csi3 csi2根据物理层分为 c-phy 和 d-phy, csi-3采用的是m-phy 一般采用csi2 c-phy 和 d-phy的区别 d-phy的时钟线和数据线是分开的,2根线一对…...

深入解析 HTML 中 `<script>` 标签的 async 和 defer 属性

一、背景与问题 在网页性能优化中&#xff0c;脚本的加载和执行方式直接影响页面渲染速度和用户体验。传统 <script> 标签的阻塞行为可能导致页面“白屏”&#xff0c;而 async 和 defer 属性提供了非阻塞的解决方案。本周重点研究二者的差异、适用场景及实际应用。 二、…...

【从0到1学Elasticsearch】Elasticsearch从入门到精通(上)

黑马商城作为一个电商项目&#xff0c;商品的搜索肯定是访问频率最高的页面之一。目前搜索功能是基于数据库的模糊搜索来实现的&#xff0c;存在很多问题。 首先&#xff0c;查询效率较低。 由于数据库模糊查询不走索引&#xff0c;在数据量较大的时候&#xff0c;查询性能很差…...

2.0 全栈运维管理:Linux网络基础核心概念解析、Proxmox网络组件详解、虚拟化网络模型分类

本文是Proxmox VE 全栈管理体系的系列文章之一&#xff0c;如果对 Proxmox VE 全栈管理感兴趣&#xff0c;可以关注“Proxmox VE 全栈管理”专栏&#xff0c;后续文章将围绕该体系&#xff0c;从多个维度深入展开。 摘要&#xff1a;Linux 网络基础借助桥接、VLAN 和 Bonding 实…...

案例驱动的 IT 团队管理:创新与突破之路: 第四章 危机应对:从风险预见到创新破局-4.1.3重构过程中的团队士气管理

&#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 &#x1f449; 点击关注不迷路 文章大纲 案例驱动的 IT 团队管理&#xff1a;创新与突破之路 - 第四章 危机应对&#xff1a;从风险预见到创新破局4.1.3 重构过程中的团队士气管理1. 技术债务重构与团队士气的矛盾2…...

洛谷刷题小结

#include <iostream> using namespace std; int n, m,ans0; char s[105][105]; //深搜 void dfs(int x, int y) {//将搜索到的水坑看为干地s[x][y] .;//确定八个方向int next[8][2] {{0,1},{0,-1},{1,0},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1},};//朝八个方向搜索for (in…...

Android Compose 权限申请完整指南

Android Compose 权限申请完整指南 在 Jetpack Compose 中处理运行时权限申请需要结合传统的权限 API 和 Compose 的状态管理。以下是完整的实现方案&#xff1a; 1. 基本权限申请流程 添加依赖 implementation "com.google.accompanist:accompanist-permissions:0.34…...

VirtualBox虚拟机转换到VMware

VirtualBox虚拟机转换到VMware **参考文章&#xff1a;**https://blog.csdn.net/qq_30054403/article/details/123451969 一.找到对应文件位置 Windows11系统&#xff0c;VirtualBox版本为6.1.50&#xff0c;VMware版本为17.5.2 1.首先找到自己需要转换的vdi文件位置 D:\v…...

Spring Boot(二十二):RedisTemplate的List类型操作

RedisTemplate和StringRedisTemplate的系列文章详见&#xff1a; Spring Boot&#xff08;十七&#xff09;&#xff1a;集成和使用Redis Spring Boot&#xff08;十八&#xff09;&#xff1a;RedisTemplate和StringRedisTemplate Spring Boot&#xff08;十九&#xff09;…...

【MySQL】关于何时使用start slave和start slave user=‘’ password=‘’

这个问题是我在配置三个服务器的复制拓扑时&#xff0c;一开始没有给复制用户 repl 创建密码&#xff0c;搭建好循环拓扑后&#xff0c;给server1的复制用户通过 ALTER USER USER() IDENTIFIED BY oracle 设置了密码&#xff0c;然后同步给了server2和server3。 这时server2突…...

(个人题解)第十六届蓝桥杯大赛软件赛省赛C/C++ 研究生组

宇宙超级无敌声明&#xff1a;个人题解&#xff08;好久不训练&#xff0c;赛中就是一个憨憨&#xff09; 先放代码吧&#xff0c;回头写思路。 文章目录 A. 数位倍数B. IPv6C. 变换数组D. 最大数字E. 冷热数据队列F. 01串G. 甘蔗H. 原料采购 A. 数位倍数 问&#xff1a; 在1至…...

GitLab + Jenkins + .Net8 实现CICD部署

前提条件&#xff1a;需要安装好 Jenkins 和 GitLab 。 1. Jenkins配置 登录 Jenkins 找到自己的一个任务&#xff0c;点击配置&#xff08;没有任务就新建&#xff09;。 按图操作 点击高级展开后截图&#xff0c;点击生成Token 配置好自己的作业&#xff08;我的是一个 .Ne…...

AI工具导航 快速找到喜欢的AI工具 功能使用介绍

此篇文章内容来源CTO Plus技术服务栈官网&#xff1a;http://www.mdrsec.com/ 在人工智能技术迅猛发展的2025年&#xff0c;AI工具的数量和种类呈爆炸式增长&#xff0c;涵盖文本生成、图像创作、视频编辑、编程辅助等多个领域。面对琳琅满目的AI工具&#xff0c;如何高效筛选和…...

[题解] Educational Codeforces Round 168 (Rated for Div. 2) E - level up

链接 思路 1 注意到在 k ∈ [ 1 , n ] k \in [1,n] k∈[1,n] 可以得到的最高等级分别为: n , n 2 , n 3 . . . . . n n n,\frac{n}{2},\frac{n}{3}.....\frac{n}{n} n,2n​,3n​.....nn​, 总的个数是一个调和级数, s u m n ∗ ln ⁡ n sumn*\ln n sumn∗lnn, 完全可以处…...

达梦数据库-学习-19-兼容ORACLE相关参数介绍

目录 一、环境信息 二、介绍 三、参数 一、环境信息 名称值CPU12th Gen Intel(R) Core(TM) i7-12700H操作系统CentOS Linux release 7.9.2009 (Core)内存4G逻辑核数2DM版本1 DM Database Server 64 V8 2 DB Version: 0x7000c 3 03134284194-202…...

如何通过 Spring 层面进行事务回滚?

Spring 中事务可以分为声明式事务和编程式事务&#xff0c;那么解下来就从这两方面说一说在 Spring 层面个怎么进行回滚 声明式事务回滚&#xff1a; 1. 基础注解配置 通过Transactional注解实现自动回滚&#xff0c;默认对RuntimeException和Error生效 Transactional publ…...

学Qt笔记

使用的是Qt SDK5.14.0 根据比特汤众老师的课程学习 先叠个甲&#xff1a;本人正在学qt&#xff0c;视角还不完备&#xff0c;如有错误请多多包含 选了widget开始学习 1.qt creator设计提供了拖拽式的编辑ui的控件&#xff0c;和代码直接编辑构建的方式 2.浅浅的认识了qt的对…...

【HarmonyOS 5】鸿蒙实现手写板

​ 【HarmonyOS 5】鸿蒙实现手写板 一、前言 实现一个手写板功能&#xff0c;基本思路如下&#xff1a; 创建一个可交互的组件&#xff0c;用户在屏幕上触摸并移动手指时&#xff0c;会根据触摸的位置动态生成路径&#xff0c;并使用黑色描边绘制在屏幕上。当用户按下屏幕时…...

JavaWeb 课堂笔记 —— 09 MySQL 概述 + DDL

本系列为笔者学习JavaWeb的课堂笔记&#xff0c;视频资源为B站黑马程序员出品的《黑马程序员JavaWeb开发教程&#xff0c;实现javaweb企业开发全流程&#xff08;涵盖SpringMyBatisSpringMVCSpringBoot等&#xff09;》&#xff0c;章节分布参考视频教程&#xff0c;为同样学习…...

设计模式 --- 访问者模式

访问者模式是一种行为设计模式&#xff0c;它允许在不改变对象结构的前提下&#xff0c;定义作用于这些对象元素的新操作。 优点&#xff1a; 1.​​符合开闭原则&#xff1a;新增操作只需添加新的访问者类&#xff0c;无需修改现有对象结构。 ​​2.操作逻辑集中管理​​&am…...

【Linux C】简单bash设计

主要功能 循环提示用户输入命令&#xff08;minibash$&#xff09;。创建子进程&#xff08;fork()&#xff09;执行命令&#xff08;execlp&#xff09;。父进程等待子进程结束&#xff08;waitpid&#xff09;。关键问题 参数处理缺失&#xff1a;scanf("%s", buf)…...

如何在Agent中设置Memory

什么是LLM代理&#xff1f; LLM代理可以被定义为能够对环境采取行动的大型语言模型。代理的主要组成部分包括&#xff1a;记忆、规划、提示、知识和工具。大型语言模型可以被视为这个架构的大脑&#xff0c;而其他所有组件则是代理正常工作的基础模块。 代理的组成部分 1. 提…...