java设计模式八 享元
享元模式(Flyweight Pattern)是一种结构型设计模式,它通过共享技术有效地支持大量细粒度的对象。这种模式通过存储对象的外部状态在外部,而将不经常变化的内部状态(称为享元)存储在内部,以此来减少内存中对象的数量。享元模式适用于那些可以共享的对象,以此来减少系统创建对象的数量,从而提升效率和性能。
### 案例分析:文字处理软件中的字符渲染
假设我们正在开发一个文字处理软件,需要显示大量的字符。每个字符可能有不同的颜色、字体和大小等属性,但字符本身(如'a', 'b', 'c'等)却是有限的。如果不使用享元模式,我们会为每个带有独特属性组合的字符创建一个对象,这会导致内存中存在大量重复的字符对象。
#### 享元模式的应用步骤:
1. **定义享元接口**:
定义一个接口或抽象类,声明一个或多个方法用于操作内部状态,通常还会有一个方法来获取外部状态。
```java
public interface Character {void display(char character, Color color, Font font);
}
```
2. **实现享元类**:
实现享元接口,并存储内部状态(在这个案例中,内部状态为空,因为字符是固定的)。
```java
public class ConcreteCharacter implements Character {@Overridepublic void display(char character, Color color, Font font) {System.out.printf("Rendering character '%c' with color %s and font %s%n", character, color, font);}
}
```
3. **创建享元工厂**:
工厂负责创建和管理享元对象,确保相同的字符复用同一个对象。为了高效地查找享元,通常会使用如HashMap这样的数据结构来存储已经创建的享元对象。```java
public class CharacterFactory {private Map<Character, ConcreteCharacter> pool = new HashMap<>();public Character getCharacter(char character) {ConcreteCharacter flyweight = pool.get(character);if (flyweight == null) {flyweight = new ConcreteCharacter();pool.put(character, flyweight);}return flyweight;}
}
```
4. **客户端代码**:
客户端从享元工厂获取享元对象,并设置外部状态(颜色、字体)后调用其方法。
```java
public class TextEditor {private CharacterFactory factory;public TextEditor() {factory = new CharacterFactory();}public void renderText(String text, Color color, Font font) {for (char c : text.toCharArray()) {Character character = factory.getCharacter(c);character.display(c, color, font);}}
}// 使用示例
TextEditor editor = new TextEditor();
editor.renderText("Hello, World!", Color.RED, Font.TIMES_ROMAN);
```
在这个例子中,尽管每个字符在屏幕上显示时可能有不同的颜色和字体,但字符本身是有限的。享元模式通过`CharacterFactory`确保了对于每个不同的字符仅创建一个`ConcreteCharacter`实例,并通过传递外部状态(颜色和字体)来展示字符的不同表现,从而极大地减少了内存占用。
继续深入,我们可以探讨享元模式的一些关键优势、应用场景及注意事项,以加深对这一设计模式的理解。
### 关键优势
1. **内存优化**:最显著的优势是大幅度减少内存中对象的数量,特别是当存在大量相似对象时。这在处理大数据量或图形密集型应用时尤为重要,能有效减少内存占用,提高系统性能。
2. **性能提升**:减少了对象的创建和销毁过程,降低了垃圾回收的压力,提升了系统的运行速度。
3. **易于维护和扩展**:通过集中管理享元对象,使得对内部状态的修改变得更加集中和容易控制。同时,新的享元类型可以轻松添加到系统中,不影响现有代码。
### 应用场景
- **图形处理**:如上述字符渲染例子,图像处理软件中的像素、图标库等。
- **大量相似对象**:游戏开发中的子弹、棋盘上的棋子等,这些对象除了位置等少数状态外,其他大部分属性都相同。
- **字符串处理**:文本编辑器中的字符或单词,特别是在实现复杂格式化时。
- **网络编程**:连接池的设计中,复用数据库连接或socket连接等资源。
### 注意事项
1. **区分内外部状态**:正确区分对象的内部状态(被享元对象管理,不随环境改变)和外部状态(由客户端控制,随环境改变)。错误地处理状态可能会导致逻辑错误或数据混乱。
2. **线程安全**:当享元对象在多线程环境下被共享时,需要考虑线程安全问题。可能需要在享元类中加入同步机制或确保外部状态的线程安全性。
3. **初始化成本**:虽然享元模式能减少运行时的内存消耗,但如果享元对象的创建成本很高,初始化大量享元可能会影响程序的启动时间。
4. **过度设计**:在对象数量不是特别庞大,或者内存不是主要瓶颈的情况下,过度使用享元模式可能会增加系统的复杂度,得不偿失。因此,是否采用享元模式需根据实际情况权衡。
通过合理运用享元模式,可以在保证程序高效、内存友好的同时,保持代码的清晰与可维护性,是面向对象设计中一项非常实用的技巧。
接下来,让我们进一步探索享元模式在实际开发中的一些高级应用技巧和设计考量,以及如何与其他设计模式结合使用,以达到更好的效果。
### 高级应用技巧
1. **使用复合享元**:当享元对象需要组合其他享元对象以形成更复杂的结构时,可以引入复合享元的概念。例如,在游戏开发中,一个复合角色可能包含武器、防具等多个独立的享元对象,通过组合这些享元来构建更丰富的实体。
2. **懒加载**:为了进一步优化内存使用,可以在享元工厂中实现享元对象的懒加载策略。即首次请求某个享元时才创建它,而不是一开始就创建所有可能用到的享元对象。
3. **缓存管理**:对于内存敏感的应用,可以实施更精细的缓存管理策略,比如设置缓存上限,当缓存超出限制时,根据某种策略(如最近最少使用LRU)移除部分享元对象。
### 与其他设计模式结合
1. **与工厂模式结合**:如之前提到的,享元工厂负责创建和管理享元对象,这是工厂模式的一个典型应用。结合工厂模式,可以更加灵活和高效地控制享元对象的生命周期和分配。
2. **与代理模式结合**:当需要为享元对象添加额外的操作或控制访问时,可以通过代理模式包装享元对象。代理可以处理外部状态的传递,以及任何与具体业务逻辑相关的操作,同时保持享元对象本身的纯粹性。
3. **与状态模式结合**:如果享元对象的行为依赖于其状态,且这些状态变化较为复杂,可以引入状态模式来管理这些状态变化。享元对象的内部状态通过状态对象表示,状态对象的变化不会影响享元对象的身份,从而维持享元的共享特性。
### 总结
享元模式是一个强大的设计工具,它通过共享技术减少系统中对象的数量,优化了内存使用并提高了性能。在设计和实现时,需要细心区分内外部状态,考虑并发访问的线程安全问题,以及选择合适的时间和场景应用该模式。通过与其他设计模式的结合使用,可以解决更为复杂的问题,构建出更加高效、灵活的系统。掌握并灵活运用享元模式,是提升软件设计质量的重要一步。
相关文章:
java设计模式八 享元
享元模式(Flyweight Pattern)是一种结构型设计模式,它通过共享技术有效地支持大量细粒度的对象。这种模式通过存储对象的外部状态在外部,而将不经常变化的内部状态(称为享元)存储在内部,以此来减…...
ELK原理详解
ELK原理详解 一、引言 在当今日益增长的数据量和复杂的系统环境中,日志数据的收集、存储、分析和可视化成为了企业运营和决策不可或缺的一部分。ELK(Elasticsearch、Logstash、Kibana)堆栈凭借其高效的性能、灵活的扩展性和强大的功能&…...
多线程学习Day09
10.Tomcat线程池 LimitLatch 用来限流,可以控制最大连接个数,类似 J.U.C 中的 Semaphore 后面再讲 Acceptor 只负责【接收新的 socket 连接】 Poller 只负责监听 socket channel 是否有【可读的 I/O 事件】 一旦可读,封装一个任务对象&#x…...
第33次CSP认证Q1:词频统计
🍄题目描述 在学习了文本处理后,小 P 对英语书中的 𝑛n 篇文章进行了初步整理。 具体来说,小 P 将所有的英文单词都转化为了整数编号。假设这 𝑛n 篇文章中共出现了 𝑚m 个不同的单词,则把它们…...
pytorch加载模型出现错误
大概的错误长下面这样: 问题出现的原因: 很明显,我就是犯了第一种错误。 网上的修改方法: 我觉得按道理哈,确实,蓝色部分应该是可以把问题解决了的。但是我没有解决,因为我犯了另外一个错…...
如何在Mac上恢复格式化硬盘的数据?
“嗨,我格式化了我的一个Mac硬盘,而没有使用Time Machine备份数据。这个硬盘被未知病毒感染了,所以我把它格式化为出厂设置。但是,我忘了备份我的文件。现在,我想恢复格式化的硬盘驱动器并恢复我的文档,您能…...
华为OD机试 - 手机App防沉迷系统(Java 2024 C卷 100分)
华为OD机试 2024C卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试(JAVA)真题(A卷B卷C卷)》。 刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试…...
搜维尔科技:光学动作捕捉系统用于城市公共安全智慧感知实验室
用户名称:西安科技大学 主要产品:Optitrack Priime41 光学动作捕捉系统(8头) 在6米8米的空间内,通过8个Optitrack Priime41光学动作捕捉镜头,对人体动作进行捕捉,得到用户想要的人体三维空间坐…...
保研面试408复习 4——操作系统、计网
文章目录 1、操作系统一、文件系统中文件是如何组织的?二、文件的整体概述三、UNIX外存空闲空间管理 2、计算机网络一、CSMA/CD 协议(数据链路层协议)二、以太网MAC帧MTU 标记文字记忆,加粗文字注意,普通文字理解。 1、…...
实战攻防中关于文档的妙用
一、PPT钓鱼 简单制作一个用于钓鱼的PPTX文件 一般那种小白不知道PPT也能拿来钓鱼,这里主要是借用PPT中的”动作按钮”, 我们在插入的地方,选择“动作按钮” 然后在弹出的窗口处: 比如填入上线CS的语句:powershell.exe -nop -w …...
【使用ChatGPT的API之前】OpenAI API提供的可用模型
文章目录 一. ChatGPT基本概念二. OpenAI API提供的可用模型1. InstructGPT2. ChatGPT3. GPT-4 三. 在OpenAI Playground中使用GPT模型-ing 在使用GPT-4和ChatGPT的API集成到Python应用程序之前,我们先了解ChatGPT的基本概念,与OpenAI API提供的可用模型…...
【C语言】模拟实现深入了解:字符串函数
🔥引言 本篇将模拟实现字符串函数,通过底层了解更多相关细节 🌈个人主页:是店小二呀 🌈C语言笔记专栏:C语言笔记 🌈C笔记专栏: C笔记 🌈喜欢的诗句:无人扶我青云志 我自…...
钩子函数onMounted定义了太多访问MySQL的操作 导致数据库异常
先放几种后端遇到的异常,多数和数据库有关 pymysql.err.InternalError: Packet sequence number wrong - got 102 expected 1 127.0.0.1 - - [09/May/2024 17:49:37] "GET /monitorLastTenList HTTP/1.1" 500 AttributeError: NoneType object has no at…...
Excel文件解析---超大Excel文件读写
1.使用POI写入 当我们想在Excel文件中写入100w条数据时,使用XSSFWorkbook进行写入时会发现,只有将100w条数据全部加载到内存后才会用write()方法统一写入,效率很低,所以我们引入了SXXFWorkbook进行超大Excel文件读写。 通过设置 …...
TypeScript基础:类型系统介绍
TypeScript基础:类型系统介绍 引言 TypeScript,作为JavaScript的一个超集,引入了类型系统,这为开发大型应用程序带来了诸多好处。本文将介绍TypeScript类型系统的基础知识,帮助初学者理解其概念和用法。 基础知识 …...
【Unity】Unity项目转抖音小游戏(一) 项目转换
UnityWEBGL转抖音小游戏流程 业务需求,开始接触一下抖音小游戏相关的内容,开发过程中记录一下流程。 相关参考: 抖音文档:https://developer.open-douyin.com/docs/resource/zh-CN/mini-game/develop/guide/game-engine/rd-to-SC…...
element-ui 中修改loading加载样式
element-ui 中的 loading 加载功能,默认是全屏加载效果 设置局部,需要自定义样式或者修改样式,方法如下: import { Loading } from element-uiVue.prototype.$baseLoading (text) > {let loadingloading Loading.service({…...
QT登录界面,(页面的切换)
以登陆界面为例,(QDialog) 1.主界面先构造login 的对话框类 int main(int argc, char *argv[]) {QApplication a(argc, argv);//先显示Login的界面Study_Login_Dialog login;............ }2.Login的类,可以用自定义的信号&#…...
计算机毕业设计 | vue+springboot汽车销售管理系统(附源码)
1,项目介绍 本项目基于spring boot以及Vue开发,前端实现基于PanJiaChen所提供的开源后台项目vue-element-admin改造。 针对汽车销售提供客户信息、车辆信息、订单信息、销售人员管理、财务报表等功能,提供经理和销售两种角色进行管理。 2&…...
一款开源的原神工具箱,专为现代化 Windows 平台设计,旨在改善桌面端玩家的游戏体验
Snap.Hutao 胡桃工具箱是一款以 MIT 协议开源的原神工具箱,专为现代化 Windows 平台设计,旨在改善桌面端玩家的游戏体验。通过将既有的官方资源与开发团队设计的全新功能相结合,提供了一套完整且实用的工具集,且无需依赖任何移动设…...
python日常消费数据占比分析总结年消费方向
欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 目录 一.前言 整体消费情况 消费趋势 特定领域消费数据...
MySQL变量的浮点数问题处理
schooldb库——utf8字符集——utf8_general_ci排序规则 先创建库,点击查询再去使用下列DQL。 DQL SET dx3.14,dy3.25; SELECT dxdy; #mysql浮点数计算显示异常,会有很多00000的提示 SET resultdxdy;select result;...
MWeb Pro for Mac:功能强大的Markdown博客编辑器
MWeb Pro for Mac是一款功能强大的Markdown博客编辑器,专为Mac用户设计,提供了一站式的博客写作和发布体验。这款软件不仅支持Markdown语法,还提供了丰富的编辑和排版功能,让用户能够轻松创建出精美的博客内容。 MWeb Pro的即时预…...
基于FPGA实现的HDMI TO MIPI扩展显示器方案
FPGA方案,HDMI IN接收原始HDMI 信号,输出显示到LCD 屏上 客户应用:扩展显示器 主要特性: 1.支持2K以下任意分辨率显示 2.支持OSD 叠加多个图层 3.支持MIPI/EDP/LVDS/RGB屏 4.支持放大缩小匹配屏分辨率 5.零延时,输…...
2024年美国市场亚太游戏品牌数字广告洞察报告
来源:Sensor Tower 美国是全球最大的游戏市场之一,也是亚太游戏品牌出海的重要市场。2023年Q2至2024年Q1,美国市场广告投放额排名前10的亚太游戏品牌,合计支出 超过7.5亿美元,环比上涨23%。 排名第一的米哈游(miHoY…...
DDD面试题:DDD聚合和表的对应关系是什么 ?(来自蚂蚁面试)
尼恩说在前面: 在40岁老架构师 尼恩的读者交流群(50)中,最近有小伙伴拿到了一线互联网企业如字节、阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格,遇到很多很重要的面试题: DDD 的外部接口调用,应该放在…...
【华为】路由策略小实验
【华为】软考中级-路由策略实验 实验需求拓扑配置AR1AR2需求1需求2 AR3 检验 实验需求 1、让 R3 可以学到R1的 192.168.10.0/24和192.168.20.0/24的 路由,不能学到192.168.30.0/24。 2、让 R1可以学到 R3 的 172.16.20.0/24和172.16.30.0/24的路由,不能…...
docker安装elasticsearch:7.17.21
docker安装elasticsearch:7.17.21 下载对应版本的docker镜像 docker pull docker.elastic.co/elasticsearch/elasticsearch:7.17.21启动容器 docker run --name elasticsearch-test -p 9200:9200 -p 9300:9300 -e "discovery.typesingle-node" -t docker.elastic.…...
10.Java对象内置结构
文章目录 Java对象内置结构1.Java对象的三个部分1.1.对象头1.2.对象体1.3.对齐字节 2.对象结构中核心字段的作用2.1.MarkWord(标记字)2.2.Class Pointer(类对象指针)2.3.Array Length(数组长度)2.4.对象体2.5.对齐字节 3.Mark Word的结构信息3.1.不同锁状态下的Mark Word字段结…...
【ITK配准】第十五期 基于运动算法的可变形配准样例
很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 公众号:VTK忠粉 前言 本文分享ITK配准中的基于运动算法的可变形配准,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ~YO 基于运…...
网站怎样做才能排名靠前/营销技巧
1. 涉及平台 平台管理、商家端(PC端、手机端)、买家平台(H5/公众号、小程序、APP端(IOS/Android)、微服务平台(业务服务) 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis 3. 前端框架…...
共青城市建设局网站/网络广告发布
简介 这节课我们将讨论如何在OSG中使用键盘和灯光。我们将会学习指定三种纹理过滤方式,学习如何使用键盘来移动场景中的立方体。 在osg中通过osgGA库来实现与用户的交互,在用户端,通常使用GUIEventAdapter类作为系统交互事件和OSG交互事件的…...
做餐饮网站建设/常用的关键词挖掘工具有哪些
昨天同事的一台电脑出了点问题,需要客服人员远程登陆解决,由于是内网,不能用team viewer这类的远程服务软件。过去看了一下,win7的系统,先在“我的电脑”右键打开“属性”,点击左边的“远程设置”ÿ…...
网站模版好建设吗/seo专业优化方法
zabbix 使用进阶(五)概述:本章内容具体如下:自定义key不带参数;自定义key可传递参数;在agent端自定义可传递参数的key,来获取nginx的状态信息:基于SNMP监控的创建和和使用࿱…...
阿里云服务器学生优惠/宁波seo外包平台
1、测试心理 上文中曾经提到过研发和测试在思路和观念上的一些矛盾。多数情况下,研发工程师并不精通软件测试的思路,因此可能会认为测试无非就是走一个流程,认为“软件测试就是证明软件不存在错误的过程”,或者“测试的目的在于证…...
上海做网站公司qinmoo/手机百度账号登录个人中心
子查询的小秘密 多表查询之间使用子查询, 需要表之间具有联系, 比如让两张表进行联系, 需要一个共同所有的标识来联系; 两张表表示两个对象, 对象之间是独立的, 通过一个字段进行了联系。 (还具…...