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

Java 与设计模式(12):享元模式

一、定义

享元模式是一种结构型设计模式,旨在有效地共享对象以减少内存使用和提高性能。该模式的核心思想是通过共享尽可能多的相似对象来减少内存占用。它将对象分为可共享的内部状态和不可共享的外部状态。内部状态是对象的固有属性,可以在多个对象之间共享,而外部状态是对象的上下文相关属性,每个对象都是独立的。

通过共享内部状态,享元模式可以减少创建相似对象的数量,从而节省内存空间。当需要创建新对象时,可以首先检查是否已经存在具有相同内部状态的对象,如果存在,则可以直接返回共享的对象,而不是创建新的对象。这种共享对象的方式可以在大规模使用相似对象的场景中提高性能和效率。

需要注意的是,享元模式需要维护一个对象池或缓存来存储共享的对象,以便在需要时进行检索。同时,外部状态的管理也需要谨慎处理,确保每个对象在不同的上下文中都能正确地使用。

享元模式通过共享相似对象的内部状态来减少内存占用和提高性能,是一种常用的优化技术。

二、Java示例

import java.util.HashMap;
import java.util.Map;// 具体享元类
class ConcreteFlyweight {private String intrinsicState;public ConcreteFlyweight(String intrinsicState) {this.intrinsicState = intrinsicState;}public void operation(String extrinsicState) {System.out.println("Intrinsic State: " + intrinsicState);System.out.println("Extrinsic State: " + extrinsicState);}
}// 享元工厂类
class FlyweightFactory {private Map<String, ConcreteFlyweight> flyweights = new HashMap<>();public ConcreteFlyweight getFlyweight(String key) {if (flyweights.containsKey(key)) {return flyweights.get(key);} else {ConcreteFlyweight flyweight = new ConcreteFlyweight(key);flyweights.put(key, flyweight);return flyweight;}}
}// 客户端代码
public class Client {public static void main(String[] args) {FlyweightFactory factory = new FlyweightFactory();ConcreteFlyweight flyweight1 = factory.getFlyweight("shared");flyweight1.operation("state 1");ConcreteFlyweight flyweight2 = factory.getFlyweight("shared");flyweight2.operation("state 2");ConcreteFlyweight flyweight3 = factory.getFlyweight("unique");flyweight3.operation("state 3");}
}

在上述示例中,ConcreteFlyweight类表示具体的享元对象,包含一个内部状态intrinsicStateFlyweightFactory类作为享元工厂,维护一个对象池flyweights,用于存储共享的享元对象。

客户端代码通过FlyweightFactory获取享元对象,并调用其operation方法进行操作。当请求的享元对象已存在于对象池中时,直接返回共享的对象;否则,创建新的享元对象并添加到对象池中。

这样,通过共享相似对象的内部状态,可以减少创建对象的数量,节省内存空间。在示例中,flyweight1flyweight2共享了相同的内部状态,而flyweight3是一个独立的对象。

三、优点

享元模式的优点包括:

  1. 减少内存占用:通过共享相似对象的内部状态,可以减少创建对象的数量,从而减少内存占用。

  2. 提高性能:由于减少了对象的数量,可以减少对象的创建和销毁过程,从而提高程序的性能。

  3. 提高对象复用性:通过共享对象,可以在不同的上下文中复用对象,避免重复创建相似的对象。

  4. 简化对象管理:享元模式将对象的内部状态和外部状态进行分离,使得对象的管理更加简单和清晰。

  5. 支持大规模对象共享:当系统中存在大量相似对象时,通过享元模式可以有效地管理和共享这些对象,提高系统的可扩展性和可维护性。

享元模式通过共享相似对象的内部状态,可以减少内存占用、提高性能和对象复用性,简化对象管理,并支持大规模对象共享。这使得享元模式成为一种有价值的优化技术。

四、缺点

享元模式的缺点包括:

  1. 对象共享可能导致线程安全问题:如果多个线程同时访问共享对象,并且修改了对象的外部状态,可能会导致线程安全问题。需要在使用享元对象时进行适当的同步控制。

  2. 对象池管理增加复杂性:享元模式需要维护一个对象池或缓存来存储共享对象,这增加了对象管理的复杂性。需要确保正确地管理对象的创建、共享和销毁,避免资源泄露或过度消耗。

  3. 对象共享可能降低系统灵活性:当对象的内部状态和外部状态耦合较高时,共享对象可能限制了系统的灵活性。如果需要修改共享对象的内部状态,可能会影响到其他共享该对象的地方。

  4. 需要额外的内部状态管理:享元模式将对象的内部状态和外部状态进行分离,需要额外的管理和维护内部状态的机制。这增加了一定的复杂性和开销。

享元模式在提高性能和减少内存占用方面有优势,但也需要考虑线程安全、对象管理复杂性以及灵活性等方面的问题。在使用时需要根据具体场景进行权衡和设计。

五、使用场景

享元模式适用于以下场景:

  1. 对象数量庞大且相似:当系统中存在大量相似的对象,并且这些对象可以共享部分或全部内部状态时,可以使用享元模式来减少对象的数量和内存占用。

  2. 对象的外部状态可分离:对象的外部状态可以被分离出来,并且可以通过参数传递给对象的方法。这样可以将对象的内部状态与外部状态分离,使得对象可以共享内部状态。

  3. 需要缓存或池化对象:如果需要频繁地创建和销毁对象,并且对象的创建和销毁过程较为耗时,可以使用享元模式来缓存或池化对象,提高性能。

  4. 系统需要支持大规模对象共享:当系统中存在大量相似对象,并且这些对象需要在不同的上下文中共享时,可以使用享元模式来管理和共享这些对象,提高系统的可扩展性和可维护性。

需要注意的是,使用享元模式需要权衡对象共享带来的线程安全问题、对象管理的复杂性以及灵活性的影响。在具体应用时,需要根据实际情况进行设计和优化。

六、注意事项

在使用享元模式时,需要注意以下几点:

  1. 线程安全性:如果多个线程同时访问共享对象,并且修改了对象的外部状态,可能会导致线程安全问题。需要在使用享元对象时进行适当的同步控制,确保线程安全。

  2. 对象池管理:享元模式需要维护一个对象池或缓存来存储共享对象,需要确保正确地管理对象的创建、共享和销毁。需要注意避免资源泄露或过度消耗。

  3. 内部状态和外部状态的划分:需要合理划分对象的内部状态和外部状态,确保内部状态可以共享,而外部状态可以通过参数传递给对象的方法。同时,需要注意内部状态和外部状态的耦合度,避免影响系统的灵活性。

  4. 对象的可变性:享元模式适用于对象的内部状态是不可变的情况。如果对象的内部状态是可变的,需要考虑如何处理共享对象的可变性,以及如何保证共享对象的一致性。

  5. 性能权衡:使用享元模式可以提高性能和减少内存占用,但也需要权衡对象共享带来的管理复杂性和灵活性的影响。在具体应用时,需要根据实际情况进行设计和优化。

使用享元模式需要综合考虑线程安全性、对象管理、内部状态和外部状态的划分、对象的可变性以及性能权衡等方面的问题。在具体应用时,需要根据实际需求和场景进行适当的设计和调整。

七、在spring 中的应用

在Spring源码中,享元模式被广泛应用于各个模块和组件中,以提高性能和减少内存占用。以下是一些Spring源码中使用享元模式的示例:

  1. Bean对象的管理:在Spring的IoC容器中,Bean对象被视为享元对象。当容器启动时,会预先创建并缓存Bean对象,以便在需要时进行共享和复用。这样可以减少对象的创建和销毁开销,提高性能。

  2. 数据库连接池:Spring的JDBC模块中,使用享元模式管理数据库连接。连接池中的连接对象被视为享元对象,可以在多个线程之间共享和复用,避免频繁地创建和销毁连接,提高数据库操作的性能。

  3. 缓存管理:Spring的缓存模块中,使用享元模式管理缓存对象。缓存对象被视为享元对象,可以在多个请求之间共享和复用,避免重复计算和查询,提高系统的响应速度。

  4. 国际化资源管理:Spring的国际化模块中,使用享元模式管理国际化资源对象。国际化资源对象被视为享元对象,可以在多个地方共享和复用,避免重复加载和解析资源文件,提高国际化功能的性能。

需要注意的是,Spring框架中对享元模式的应用往往是隐式的,封装在各个模块和组件中,不会直接暴露给开发者。这样可以提供更加简洁和易用的API,同时隐藏了底层的实现细节。

相关文章:

Java 与设计模式(12):享元模式

一、定义 享元模式是一种结构型设计模式&#xff0c;旨在有效地共享对象以减少内存使用和提高性能。该模式的核心思想是通过共享尽可能多的相似对象来减少内存占用。它将对象分为可共享的内部状态和不可共享的外部状态。内部状态是对象的固有属性&#xff0c;可以在多个对象之…...

React配置代理(proxy)

使用axios进行请求&#xff0c;而配置代理过程。 第一种 在package.json中&#xff0c;添加proxy配置项,之后所有的请求都会指向该地址 但这种方法只能配置一次&#xff0c;也只有一个 示例&#xff1a; "proxy":"https://localhost:5000" 添加后&am…...

队列(Queue):先进先出的数据结构队列

栈与队列https://blog.csdn.net/qq_45467165/article/details/127958960?csdn_share_tail%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22127958960%22%2C%22source%22%3A%22qq_45467165%22%7D 队列&#xff08;Queue&#xff09;是一种常见的线…...

CentOS ens160 显示disconnected

使用nmcli device查看网卡状态&#xff0c;显示如图&#xff1a; 检查宿主机系统VMware DHCP Sevice和VMware NAT Sevice服务是否正常运行。 右键点击我的电脑管理按钮&#xff0c;打开计算机管理点击服务...

使用 ChatGPT 创建 PowerPoint 演示文稿

让 ChatGPT 成为您的助手来帮助您编写电子邮件很简单,因为众所周知,它非常能够生成文本。很明显,ChatGPT 无法帮助您做饭。但您可能想知道它是否可以生成文本以外的其他内容。在上一篇文章中,您了解到 ChatGPT 只能通过中间语言为您生成图形。在这篇文章中,您将了解使用中…...

matlab将数组值划分为两类

例如&#xff1a;大于0的处理为1&#xff0c;小于0的处理为-1. 当然&#xff0c;可以选择循环结构和选择结构&#xff0c;但是效率会很低。 这里直接使用逻辑语句完成。 % 不使用循环语句&#xff0c;将数组内值划分为两类 clc; clearvars; a[-0.1422 , -0.0433 , 0.1131 …...

【点击新增一个下拉框 与前一个内容一样 但不能选同一个值】

点击新增一个下拉框 与前一个内容一样 但不能选同一个值 主要是看下拉选择el-option的disabled,注意不要混淆 <el-form label-width"120px" :model"form" ref"form" style"color: #fff"><template v-for"(trapolicy, i…...

【Gitee提交pr】

Gitee提交pr 什么是pr怎样提交一个pr嘞&#xff1f; 什么是pr pr:指的是将自己的修改从自己的账号仓库dev下提交到官方账号仓库master下&#xff1b; 通俗来讲就是Gitee线上有属于自己的分支&#xff0c;然后本地在自己地分支修改完代码之后&#xff0c;提交到自己的线上分支&a…...

一款打工人必备的电脑端自律软件!!冲鸭打工人!!

你&#xff01;有没有渴望进步&#xff01;&#xff01; 你&#xff01;有没有渴望变强&#xff01;&#xff01;&#xff01; 成为大佬&#xff01;&#xff01;&#xff01;超越巨佬&#xff01;&#xff01;&#xff01; 这就是一款为这样的你量身定做的程序&#xff1a;输入…...

【Vue框架】 router和route是什么关系

前言 之前没太注意&#xff0c;写着写着突然发现它们貌似不太一样&#xff0c;记录以下&#xff0c;回顾的看总结就好。 1、总结✨ route&#xff1a;当前激活路由的对象&#xff0c;用于访问和操作当前路由的信息 router&#xff1a;管理多个route的对象&#xff0c;整个应…...

整理mongodb文档:聚合管道

个人博客 整理mongodb文档:聚合管道 个人博客&#xff0c;求关注&#xff0c;电脑版看体验更加&#xff0c;如果不够清晰&#xff0c;请指出来&#xff0c;谢谢 文章概叙 文章主要通过几个常用的聚合表达式来介绍聚合管道的使用&#xff0c;以及从索引的角度来介绍聚合管道…...

Delphi 11.3 FMX 多设备平台中使用 TGrid 实现类似 TDBGrid 的效果

Delphi Firemonkey 中 TDBGrid 这个控件已经没有了。如何实现类似这个效果呢。其实可以用TGrid 来实现。以下用 11.3 来讲解。 查询里面用到的 connection 和 query 等控件那些一般的数据库用法&#xff0c;就不做过多描述了。请参考其他资料。 方法一.通过界面配置来实现 在…...

Qt-事件循环与QtConcurrent、QThread结合使用时注意的点

QEventLoop和QtConcurrent可以结合使用达到主线程ui不阻塞同步执行的效果&#xff0c;但是要小心避坑&#xff0c;查看如下代码&#xff1a; QEventLoop loop; QtConcurrent::run([&]() {doSomething();loop.quit(); }); loop.exec();上述写法存在两个问题&#xff1a; Q…...

基于MongoDB的空间数据存储与查询

一、概念说明 1.1 空间地理数据 MongoDB 中使用 GeoJSON对象 或 坐标对 描述空间地理数据。MongoDB使用 WGS84 参考系进行地理空间数据查询。 1、MongoDB支持空间数据的存储&#xff0c;数据类型需要限制为GeoJSON; 2、MongoDB可以为GeoJSON类型数据建立索引&#xff0c;提升空…...

jquery中pdf的上传、下载及excel导出

jquery中pdf的上传、下载及excel导出 1.PDF上传 pdfUpload2. pdf下载和excel导出用的一种方法&#xff0c;并且需要引入utils.js2.1PDF下载 pdfDownload2.2导出Excel excelExport 1.PDF上传 pdfUpload //PDF上传 pdfUpload window.pdfUploadfunction (obj){layer.open({type:…...

【MyBatis】:PageHelper分页插件与特殊字符处理

目录 一、PageHelper介绍 二、PageHelper使用 1. 导入pom依赖 2. Mybatis.cfg.xml 配置拦截器 3. 配置 Mapper.xml 4. 编写测试 三、特殊字符处理 1. 使用转义字符 2. 使用CDATA 区段 一、PageHelper介绍 PageHelper 是 Mybatis 的一个插件&#xff0c;这里就不扯了&a…...

C语言练习1(巩固提升)

C语言练习1 选择题 前言 “人生在勤&#xff0c;勤则不匮。”幸福不会从天降&#xff0c;美好生活靠劳动创造。全面建成小康社会的奋斗目标&#xff0c;为广大劳动群众指明了光明的未来&#xff1b;全面建成小康社会的历史任务&#xff0c;为广大劳动群众赋予了光荣的使命&…...

eCharts热力图Y轴左上角少一块

问题&#xff1a; 如图 在图例的左上角 Y轴会少一块 官方demo https://echarts.apache.org/examples/zh/editor.html?cheatmap-cartesian 事实上 把官方demo的左上角坐标 [ 6, 0, 1 ] 修改为 [ 6, 0, 0 ] 后 依旧会出现该问题 查遍文档 并无解释 也没有任何配置项可解决…...

RabbitMQ介绍

RabbitMQ的概念 RabbitMQ 是一个消息中间件&#xff1a;它接受并转发消息。你可以把它当做一个快递站点&#xff0c;当你要发送一个包裹时&#xff0c;你把你的包裹放到快递站&#xff0c;快递员最终会把你的快递送到收件人那里&#xff0c;按照这种逻辑 RabbitMQ 是 一个快递…...

玩转软件|钉钉个人版内测启动:AI探索未来的工作方式

目录 前言 正文 AI为核心&#xff0c;个人效率为王&#xff01; 指令中心&#xff0c;解锁AI技巧&#xff01; 灵感Store&#xff0c;探索更多可能&#xff01; 未来的AI&#xff0c;即将问世&#xff01; 个人内测体验 前言 重磅消息&#xff1a;钉钉个人版在8月16日正…...

ETS5保姆级教程:从零配置KNX智能开关,实现灯光、窗帘、场景联动

ETS5保姆级教程&#xff1a;从零配置KNX智能开关&#xff0c;实现灯光、窗帘、场景联动 KNX作为智能家居领域的国际标准协议&#xff0c;以其稳定性和灵活性备受推崇。而ETS5则是配置KNX系统的核心工具&#xff0c;掌握它意味着你能够自由定制属于自己的智能家居方案。本教程将…...

EnCase、FTK还是取证大师?2024年主流电子取证工具横评与选型指南(附学习路径)

EnCase、FTK还是取证大师&#xff1f;2024年电子取证工具选型与职业发展全指南 当你的硬盘突然变成犯罪现场&#xff0c;键盘敲击声就是指纹&#xff0c;而每一串代码都可能成为呈堂证供——这就是电子取证专家的日常。在这个数据爆炸的时代&#xff0c;电子取证已从警方的技术…...

刚刚!美团开源LongCat-Next,全模态模型保姆级教程(非常详细),从入门到精通,建议收藏!

昨天下午刷到了美团龙猫团队又开源了一个新模型-LongCat-Next。 这次有所不同&#xff0c;是一个原生全模态模型&#xff0c;可以接受文本、语音、图像的输入&#xff0c;生成文本、语音、图像&#xff0c;激活参数3B。 在训练上&#xff0c;通过分词器-反分词器对&#xff0…...

Clawdbot+Qwen3-32B部署指南:Ollama模型注册与配置详解

ClawdbotQwen3-32B部署指南&#xff1a;Ollama模型注册与配置详解 1. 开始前的准备&#xff1a;理解Clawdbot与Qwen3-32B的关系 在动手之前&#xff0c;先理清楚几个关键概念。Clawdbot&#xff08;现在已更名为OpenClaw&#xff09;本质上是一个智能代理框架&#xff0c;它本…...

WiFi CSI感知技术全攻略:从原理到实践的深度探索

WiFi CSI感知技术全攻略&#xff1a;从原理到实践的深度探索 【免费下载链接】Awesome-WiFi-CSI-Sensing A list of awesome papers and cool resources on WiFi CSI sensing. 项目地址: https://gitcode.com/gh_mirrors/aw/Awesome-WiFi-CSI-Sensing 一、技术原理&…...

新手入门:在快马上亲手实现第一个限流器,看懂‘rate limit exceeded’

最近在学习后端开发时&#xff0c;经常遇到"rate limit exceeded"这个错误提示。作为新手&#xff0c;一开始完全不明白这是什么意思&#xff0c;直到在InsCode(快马)平台上动手实现了一个简单的限流器&#xff0c;才真正理解了它的原理。今天就来分享一下这个入门项…...

1元一包的“干脆面”,为什么一年卖了近5亿包?——从康师傅财报看休闲食品的“新风口”!

近日&#xff0c;市场上出现了一个让人意想不到的现象&#xff1a;1元左右就能买到的一包干脆面&#xff0c;竟然在2025年卖出了接近5亿包&#xff01;这一现象背后&#xff0c;折射出了方便面行业从“主食”向“休闲零食”角色的成功转变&#xff0c;以及消费观念的深刻变迁。…...

Hunyuan-MT Pro实操手册:对接LangChain构建带记忆的多轮专业咨询翻译Bot

Hunyuan-MT Pro实操手册&#xff1a;对接LangChain构建带记忆的多轮专业咨询翻译Bot 1. 项目概述与目标 Hunyuan-MT Pro 是基于腾讯混元翻译模型的现代化Web翻译终端&#xff0c;而今天我们要做的是让它变得更智能——通过集成LangChain框架&#xff0c;构建一个具备对话记忆…...

手把手教你用FastBlur打造高级感UI:从对话框背景到沉浸式音乐播放器的完整实现

用FastBlur打造高级UI的实战指南&#xff1a;从对话框到音乐播放器的设计进化 毛玻璃效果早已从iOS的视觉语言演变为现代移动应用设计的通用元素。这种半透明模糊效果不仅能提升界面层次感&#xff0c;还能在不分散用户注意力的情况下创造视觉焦点。本文将带你深入Android平台实…...

雀魂智能辅助:从零构建你的AI麻将教练系统

雀魂智能辅助&#xff1a;从零构建你的AI麻将教练系统 【免费下载链接】Akagi A helper client for Majsoul 项目地址: https://gitcode.com/gh_mirrors/ak/Akagi 想在雀魂对局中获得实时AI分析与策略指导&#xff1f;雀魂智能辅助系统通过深度学习技术&#xff0c;为玩…...