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

享元模式的理解和实践

        在软件开发中,性能优化是一个永恒的话题。在追求高性能的过程中,减少内存的使用是一项重要的任务。享元模式(Flyweight Pattern)就是一种用于减少内存使用量的设计模式,它特别适用于存在大量重复对象的场景。本文将详细介绍享元模式的概念、原理、优点和缺点,并通过Java代码示例展示其实际应用。

 

一、享元模式的概念

        享元模式是一种结构型设计模式,它通过共享对象来减少内存的使用。享元(Flyweight)指的是可以共享的对象,这些对象具有内部状态(Intrinsic State)和外部状态(Extrinsic State)之分。内部状态是存储在享元对象内部的状态,可以在多个客户端之间共享;外部状态是由客户端保存的状态,它在享元对象被使用时被传入。

        享元模式的核心思想是:通过共享已经存在的对象,而不是每次需要时都创建新的对象,从而减少内存的使用。享元模式通常与工厂模式结合使用,通过一个工厂类来管理享元对象的创建和共享。

二、享元模式的原理

        享元模式的原理可以用以下步骤来概括:

  1. 定义享元接口:定义一个接口,用于声明享元对象的方法。
  2. 实现具体享元类:实现享元接口,并包含内部状态。如果需要,也可以包含一个方法用于设置外部状态。
  3. 创建享元工厂类:工厂类用于创建和管理享元对象。它维护一个存储享元对象的池(Pool),并根据请求返回相应的享元对象。
  4. 客户端代码:客户端代码通过享元工厂获取享元对象,并设置外部状态,然后调用享元对象的方法。

三、享元模式的优点和缺点

优点

  1. 减少内存使用:通过共享对象,显著减少了内存的使用量。
  2. 提高性能:减少了对象的创建和销毁,提高了系统的性能。
  3. 易于管理:享元工厂类集中管理享元对象,方便进行管理和维护。

缺点

  1. 增加了系统的复杂性:需要区分内部状态和外部状态,增加了代码的复杂性。
  2. 不适用于所有场景:只有在存在大量重复对象的场景下,享元模式才能发挥其优势。如果对象数量不多,反而会增加系统的开销。

四、享元模式的Java实现

        下面通过一个具体的例子来展示享元模式的实现。假设我们有一个表示字符的类,每个字符对象都有一个唯一的字符标识(内部状态)和一个显示位置(外部状态)。我们可以使用享元模式来共享这些字符对象。

定义享元接口

public interface Flyweight {void display(String extrinsicState);
}

实现具体享元类

import java.util.HashMap;
import java.util.Map;public class CharacterFlyweight implements Flyweight {private final char intrinsicState;private static final Map<Character, CharacterFlyweight> pool = new HashMap<>();// 私有构造函数,通过工厂方法创建对象private CharacterFlyweight(char intrinsicState) {this.intrinsicState = intrinsicState;}// 工厂方法,用于获取享元对象public static CharacterFlyweight getInstance(char intrinsicState) {CharacterFlyweight flyweight = pool.get(intrinsicState);if (flyweight == null) {flyweight = new CharacterFlyweight(intrinsicState);pool.put(intrinsicState, flyweight);}return flyweight;}@Overridepublic void display(String extrinsicState) {System.out.println("Character: " + intrinsicState + " at position: " + extrinsicState);}
}

客户端代码

public class FlyweightPatternDemo {public static void main(String[] args) {// 获取享元对象并设置外部状态Flyweight flyweight1 = CharacterFlyweight.getInstance('A');flyweight1.display("Top-Left");Flyweight flyweight2 = CharacterFlyweight.getInstance('B');flyweight2.display("Top-Right");// 获取相同的享元对象,并设置不同的外部状态Flyweight flyweight3 = CharacterFlyweight.getInstance('A');flyweight3.display("Bottom-Left");// 验证是否为同一个对象System.out.println(flyweight1 == flyweight3);  // 输出: true}
}

        在这个例子中,CharacterFlyweight类实现了Flyweight接口,并通过一个静态的pool来存储已经创建的享元对象。getInstance方法用于获取享元对象,如果对象已经存在,则直接返回;如果不存在,则创建新的对象并放入池中。客户端代码通过调用getInstance方法获取享元对象,并设置外部状态,然后调用display方法显示字符和位置信息。

        运行上述代码,输出如下:

Character: A at position: Top-Left
Character: B at position: Top-Right
Character: A at position: Bottom-Left
true

        可以看到,字符'A'的享元对象是共享的,flyweight1flyweight3实际上是同一个对象。

总结

        享元模式是一种用于减少内存使用量的设计模式,它通过共享对象来减少内存的使用。享元模式适用于存在大量重复对象的场景,通过区分内部状态和外部状态,实现对象的共享。虽然享元模式增加了系统的复杂性,但在合适的场景下,它能够显著提高系统的性能和减少内存的使用。通过Java代码示例,我们展示了享元模式的实现和应用,希望能够帮助读者更好地理解和实践这一设计模式。

相关文章:

享元模式的理解和实践

在软件开发中&#xff0c;性能优化是一个永恒的话题。在追求高性能的过程中&#xff0c;减少内存的使用是一项重要的任务。享元模式&#xff08;Flyweight Pattern&#xff09;就是一种用于减少内存使用量的设计模式&#xff0c;它特别适用于存在大量重复对象的场景。本文将详细…...

Unreal Engine 中的UI界面开发

推荐的使用方式 轻量级 HUD:使用 Canvas 绘制简单的文本、调试信息或基础 UI(如准星、血量条等)。 复杂 UI:使用 UMG(Unreal Motion Graphics)和 Slate 进行布局和交互,避免手动管理 Canvas 绘制。 避免遮挡场景:仅绘制必要的内容,并利用透明度(如 FLinearColor(1, 1…...

Docker在Ubuntu和CentOS系统下的安装

目录 1. 各版本平台支持情况2. 在Ubuntu系统下安装docker3. 常见报错4. Docker的镜像源修改5. Docker目录修改6. 在CentOS系统下安装docker 1. 各版本平台支持情况 &#xff08;1&#xff09;平台支持情况如下&#xff1a; Server 版本 桌面版本 2. 在Ubuntu系统下安装docker…...

EXCEL 关于plot 折线图--频度折线图的一些细节

目录 0 折线图有很多 1 频度折线图 1.1 直接用原始数据做的频度折线图 2 将原始数据生成数据透视表 3 这样可以做出了&#xff0c;频度plot 4 做按某字段汇总&#xff0c;成为累计plot分布 5 修改上面显示效果&#xff0c;做成百分比累计plot频度分布 0 折线图有很多 这…...

Hive操作案例

目录 idea/dg远程连接导入数据建表数据导入 idea/dg远程连接 hive的详细安装不多展示&#xff0c;自行搜索即可。 依次启动zookeeper&#xff0c;hadoop 在zookeeper的节点上启动如下指令&#xff08;我的是1个主节点和2个备用节点&#xff09; 启动Hive的metastore&#xff0…...

C++ 内存管理和模板与STL

此篇目是之后各种C库的基础 目录 内存管理 内存分布 内存管理方式 new和delete operator new 与 operator delete函数 实现原理 定位new表达式(placement-new) 模板基础 泛型编程 模板 函数模板 类模板 STL 组成部分 内存管理 内存分布 int globalVar 1; //全局变量 静…...

JDK8新特性:Stream

JDK8最大的改变&#xff1a; 1. lambda表达式 2. Stream 1. Steam流的入门 什么是Stream&#xff1f; 也叫Stream流&#xff0c;是jdk8开始的一套API&#xff0c;用于操作集合或者数组中的数据 优点&#xff1a; Stream流大量结合了Lambda的语法风格来创建&#xff0c;提…...

前端传入Grule,后端保存到 .grl 文件中

前端传入Grule&#xff0c;后端保存到 .grl 文件中 通过简单的输入框&#xff0c;将Grule的部分拆解成 规则名称 规则描述 规则优先级 规则条件 规则逻辑Grule关键字 when Then 模拟了 if 判断的条件和逻辑部分 类似于 shell 和 ruby 之类的脚本语言&#xff0c;有 then 关键字…...

探索《Crypto Rumble》 游戏:经济模型篇

《Crypto Rumble》是一款基于 Zypher Network 游戏引擎打造的卡牌 RPG三消品类的 Web3 游戏&#xff0c;通过引人入胜的游戏设计以及轻量化的游戏玩法&#xff0c;《Crypto Rumble》不仅能够为玩家带来引人入胜的沉浸式游戏体验&#xff0c;同时基于 AI Bot 的游戏编辑器&#…...

【CSS in Depth 2 精译_072】第 12 章 CSS 排版与间距概述 + 12.1 间距设置(上):究竟该用 em 还是 px

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第四部分 视觉增强技术 ✔️【第 12 章 CSS 排版与间距】 ✔️ 12.1 间距设置 ✔️ 12.1.1 使用 em 还是 px ✔️12.1.2 对行高的深入思考12.1.3 行内元素的间距设置 文章目录 第 12 章 排版与间距…...

Elasticsearch对象映射

Spring Data Elasticsearch对象映射是将Java对象&#xff08;域实体&#xff09;映射到存储在Elasticsearchs中的JSON表示形式并返回的过程。内部用于此映射的类是MappingElasticsearchConverter。 元模型对象映射 基于元模型的方法使用域类型信息对Elasticsearch进行读写操作…...

Oracle 19c rac 补丁升级,从19.7 to19.22-集群

1. 补丁包概述 数据库环境 角色 数据库 IP地址 数据库版本 主机名 数据库名称 源端 RAC 172.30.21.166/167 19.7 hfcwdb66/hfcwdb67 hfdb 将以下补丁包上传到/soft下 上传到两个节点的soft目录下&#xff1a;p6880880_190000_Linux-x86-64.zip &#xff08;更新o…...

机器学习--Kaggle的使用

机器学习–Kaggle的使用 打开Kaggle: Your Machine Learning and Data Science Community并点击Sign In登录账号 kaggle中自带了很多的数据集 在点击Datasets之后&#xff0c;单点Notebook&#xff0c;如果有适用的数据集可以单击Copy and Edit复制其Notebook&#xff0c;之后…...

客户服务新突破,天润融通助力电动车企业实现数智化转型

近年来&#xff0c;两轮电动车成为年轻人喜爱的出行新方式&#xff0c;借着这种潮流&#xff0c;许多新兴品牌迅速发展&#xff0c;并跻身行业头部。 但问题也随之而来&#xff0c;由于业务快速发展&#xff0c;各类服务问题也开始增多。 比如天润融通服务的一家头部两轮电动…...

力扣题目 - 2931.购买物品的最大开销

题目 还需要你前往力扣官网查看详细的题目要求 地址 思路 这边需要你去力扣官网详细查看题目看了题目提供的示例 已经有了解法, 先把values转成1维数组,排序之后进行累加即可 代码 var maxSpending function (values) {let list values.flat();list.sort((a, b) > a - …...

智慧化工园区自动化在线监测,建立产业链路数字安全网

智慧化工升级国家政策推动安全风险频发 化工园区作为化工产业的核心集聚地&#xff0c;在全球经济中占据重要地位。为推动行业的高质量发展&#xff0c;国家相继发布了《“十四五”危险化学品安全生产规划方案》、《石化化工行业数字化转型实施指南》和《化工园区安全风险智能化…...

在Docker中运行MySQL的思考:挑战与解决方案

引言 在云计算和容器化技术日益普及的今天&#xff0c;Docker作为一种轻量级的容器化平台&#xff0c;已经成为开发和部署应用的首选工具之一。其提供的便携性、可扩展性和环境一致性对于无状态微服务来说无疑是巨大的福音。然而&#xff0c;并非所有应用都适合在Docker容器中…...

Linux中所有和$有关的操作

prog < file 命令在 Shell 编程中用于 输入重定向&#xff0c;它将文件的内容作为程序的输入。即&#xff0c;程序 prog 会从文件 file 中读取数据&#xff0c;而不是从标准输入&#xff08;通常是键盘&#xff09;读取数据。 基本语法&#xff1a; prog < file 解释&…...

github操作学习笔记(杂乱版)

git开源的分布式版本控制系统&#xff1a; 每次修改文件提交后&#xff0c;都会自动创建一个项目版本 查看git版本看有没有安装成功&#xff1a;git --version 把默认编辑器设置成vim&#xff1a;git config --global core.editor "vim" 1、设置昵称和邮箱&#xff…...

学习思考:一日三问(思考篇)之路由表

学习思考&#xff1a;一日三问&#xff08;思考篇&#xff09;之路由表 学了什么&#xff08;是什么&#xff09;Destination/Mask&#xff08;最终目标&#xff0c;寻路必须&#xff09;Proto&#xff08;择优可选&#xff09;Pre&#xff08;择优可选&#xff09;Cost&#x…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战

前言 现在我们有个如下的需求&#xff0c;设计一个邮件发奖的小系统&#xff0c; 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查

在对接支付宝API的时候&#xff0c;遇到了一些问题&#xff0c;记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误&#xff0c;它们的含义、原因和解决方法都有显著区别。以下是详细对比&#xff1a; 1. HTTP 406 (Not Acceptable) 含义&#xff1a; 客户端请求的内容类型与服务器支持的内容类型不匹…...

椭圆曲线密码学(ECC)

一、ECC算法概述 椭圆曲线密码学&#xff08;Elliptic Curve Cryptography&#xff09;是基于椭圆曲线数学理论的公钥密码系统&#xff0c;由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA&#xff0c;ECC在相同安全强度下密钥更短&#xff08;256位ECC ≈ 3072位RSA…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...