享元模式(Flyweight)
享元模式是一种结构型设计模式,主要通过共享技术有效地减少大量细粒度对象的复用,以减少内存占用和提高性能。由于享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻量级模式。
Flyweight is a structural pattern, which effectively reduces the reuse of a large number of fine-grained objects through sharing technology to reduce memory consumption and improve performance. Since the flyweight pattern requires that objects that can be shared must be fine-grained objects, it is also called lightweight mode.
结构设计
Flyweight: 抽象享元类,包含原始对象中部分能在多个对象中共享的状态。 同一享元对象可在许多不同情景中使用。 享元中存储的状态被称为 “内在状态”。 传递给享元方法的状态被称为 “外在状态”。
ConcreteFlyweight: 具体享元类,实现享元接口,并为内部状态(如果存在的话)增加存储空间。
UnsharedConcreteFlyweight: 非共享具体享元类,抽象享元类使共享成为可能,但并不强制共享。
FlyweightFactory: 享元工厂类, 享元工厂会对已有享元的缓存池进行管理。 有了工厂后, 客户端就无需直接创建享元, 它们只需调用工厂并向其传递目标享元的一些内在状态即可。 工厂会根据参数在之前已创建的享元中进行查找, 如果找到满足条件的享元就将其返回; 如果没有找到就根据参数新建享元。
享元模式类图表示如下:
伪代码实现
接下来将使用代码介绍下享元模式的实现。
// 1、抽象享元类,存储的状态被称为 "内在状态"。 传递给享元方法的状态被称为 "外在状态"
public abstract class Flyweight {private String intrinsic;protected String extrinsic;public Flyweight(String extrinsic) {this.extrinsic = extrinsic;}public abstract void operation(String extrinsic);
}
// 2、具体享元类,实现享元接口
public class ConcreteFlyweight extends Flyweight {public ConcreteFlyweight(String extrinsic) {super(extrinsic);}@Overridepublic void operation(String extrinsic) {System.out.println("do some thing in the concrete flyweight instance");}
}
// 3、非共享具体享元类,抽象享元类使共享成为可能,但并不强制共享
public class UnsharedConcreteFlyweight extends Flyweight {public UnsharedConcreteFlyweight(String extrinsic) {super(extrinsic);}@Overridepublic void operation(String extrinsic) {System.out.println("do some thing in the unshared concrete flyweight instance");}
}
// 4、享元工厂类, 享元工厂会对已有享元的缓存池进行管理。 有了工厂后, 客户端就无需直接创建享元,
// 它们只需调用工厂并向其传递目标享元的一些状态即可
public class FlyweightFactory {private static final Map<String, Flyweight> pool = new HashMap<>();public static Flyweight getFlyweight(String extrinsic) {Flyweight flyweight = pool.get(extrinsic);if (flyweight == null) {flyweight = new ConcreteFlyweight(extrinsic);pool.put(extrinsic, flyweight);System.out.println("put a fly weight instance to the pool");}return flyweight;}
}
// 5、客户端调用
public class FlyweightClient {public void test() {// 从享元工厂获取享元类Flyweight flyweight1 = FlyweightFactory.getFlyweight("one");// 执行享元方法flyweight1.operation("one");// 从享元工厂获取重复享元类(直接从缓存池获取)Flyweight flyweight2 = FlyweightFactory.getFlyweight("one");flyweight2.operation("one");// 获取非共享享元子类Flyweight unsharedConcreteFlyweight = new UnsharedConcreteFlyweight("two");unsharedConcreteFlyweight.operation("two");}
}
适用场景
在以下情况下可以考虑使用享元模式:
(1) 一个系统有大量相同或者相似的对象,由于这类对象的大量使用,造成内存的大量耗费。
应用该模式所获的收益大小取决于使用它的方式和情景。它在下列情况中最有效:
程序需要生成数量巨大的相似对象
这将耗尽目标设备的所有内存
对象中包含可抽取且能在多个对象间共享的重复状态
(2) 对象的大部分状态都可以外部化,可以将这些外部状态传入对象中。
使用享元模式需要维护一个存储享元对象的享元池,而这需要耗费资源,因此,应当在多次重复使用享元对象时才值得使用享元模式。
优缺点
享元模式有以下优点:
(1) 节省内存。享元模式的优点在于它可以极大减少内存中对象的数量,使得相同对象或相似对象在内存中只保存一份。如果程序中有很多相似对象,那么可以考虑使用该模式
(2) 享元模式的外部状态相对独立,而且不会影响其内部状态,从而使得享元对象可以在不同的环境中被共享
但是享元模式也存在以下缺点:
(1) 可能需要牺牲执行速度来换取内存,为了使对象可以共享,享元模式需要将享元对象的状态外部化,而读取外部状态使得运行时间变长。
(2) 代码会变得更加复杂。 需要分离出内部状态和外部状态,这使得程序的逻辑复杂化
参考
《设计模式 可复用面向对象软件的基础》 Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides 著, 李英军, 马晓星等译
https://design-patterns.readthedocs.io/zh_CN/latest/structural_patterns/flyweight.html 享元模式
https://refactoringguru.cn/design-patterns/flyweight 享元模式
https://www.runoob.com/design-pattern/flyweight-pattern.html 享元模式
https://www.cnblogs.com/adamjwh/p/9070107.html 简说设计模式——享元模式
https://blog.csdn.net/ShuSheng0007/article/details/116424138 秒懂设计模式之享元模式
相关文章:

享元模式(Flyweight)
享元模式是一种结构型设计模式,主要通过共享技术有效地减少大量细粒度对象的复用,以减少内存占用和提高性能。由于享元模式要求能够共享的对象必须是细粒度对象,因此它又称为轻量级模式。 Flyweight is a structural pattern, which effecti…...

Cilium系列-11-启用带宽管理器
系列文章 Cilium 系列文章 前言 将 Kubernetes 的 CNI 从其他组件切换为 Cilium, 已经可以有效地提升网络的性能. 但是通过对 Cilium 不同模式的切换/功能的启用, 可以进一步提升 Cilium 的网络性能. 具体调优项包括不限于: 启用本地路由(Native Routing)完全替换 KubeProx…...

无人机自动返航的关键技术有哪些
无人机的广泛应用使得无人机自动返航技术变得至关重要。在各种应对意外情况的背景下,无人机自动返航技术的发展对确保无人机的安全,以及提高其应用范围具有重要意义。接下来,便为大家详细介绍无人机自动返航所运用到的关键技术。 一、定位与导…...

Vision Transformer (ViT):图像分块、图像块嵌入、类别标记、QKV矩阵与自注意力机制的解析
作者:CSDN _养乐多_ 本文将介绍Vision Transformers (ViT)中的关键点。包括图像分块(Image Patching)、图像块嵌入(Patch Embedding)、类别标记、(class_token)、QKV矩…...
Mybatis:一对多映射处理
Mybatis:一对多映射处理 前言一、概述二、创建数据模型三、问题四、解决方案1、方案一:collection(嵌套结果)2、方案二:分步查询(嵌套查询) 前言 本博主将用CSDN记录软件开发求学之路上的亲身所…...

HTML+CSS+JavaScript:全选与反选案例
一、需求 1、单击全选按钮,下面三个复选框自动选中,再次单击全选按钮,下面三个复选框自动取消选中 2、当下面三个复选框全都选中时,全选按钮自动选中,下面三个复选框至少有一个未选中,全选按钮自动取消选…...

Python 程序设计入门(001)—— 安装 Python(Windows 操作系统)
Python 程序设计入门(001)—— 安装 Python(Windows 操作系统) 目录 Python 程序设计入门(001)—— 安装 Python(Windows 操作系统)一、下载 Python 安装包二、安装 Python三、测试&…...

【redis】创建集群
这里介绍的是创建redis集群的方式,一种是通过create-cluster配置文件创建部署在一个物理机上的伪集群,一种是先在不同物理机启动单体redis,然后通过命令行使这些redis加入集群的方式。 一,通过配置文件创建伪集群 进入redis源码…...

linux 配置nacos遇见的问题及解决办法
本次的集群是启动一个服务的三个不同端口,配置如下: 一.application.properties 加上下列配置,目的是使用自己的mysql数据库: spring.datasource.platformmysql db.num1 db.url.0jdbc:mysql://127.0.0.1:3306/nacos_config?s…...

小程序开发趋势:探索人工智能在小程序中的应用
第一章:引言 小程序开发近年来取得了快速的发展,成为了移动应用开发的重要一环。随着人工智能技术的飞速发展,越来越多的企业开始探索如何将人工智能应用于小程序开发中,为用户提供更智能、便捷的服务。本文将带您一起探索人工智能…...

基于埋点日志数据的网络流量统计 - PV、UV
水善利万物而不争,处众人之所恶,故几于道💦 文章目录 一、 网站总流量数统计 - PV 1. 需求分析 2. 代码实现 方式一 方式二 方式三:使用process算子实现 方式四:使用process算子实现 二、网站独立访客数统计 - UV 1. …...

cuda入门demo(2)——最基础的二方向sobel
⚠️主要是自己温习用,只保证代码正确性,不保证讲解的详细性。 今天继续总结cuda最基本的入门demo。很多教程会给你说conv怎么写,实际上sobel也是conv,并且conv本身已经用torch实现了。 之前在课题中尝试了sobel的变体࿰…...

软件外包开发的后台开发语言
在软件外包开发中,后台语言的选择通常取决于项目需求、客户偏好、团队技能和开发效率。今天和大家分享一些常用的后台语言及选择它们的原因,希望对大家有所帮助。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎交流合作。…...

自动驾驶感知系统-全球卫星定位系统
卫星定位系统 车辆定位是让无人驾驶汽车获取自身确切位置的技术,在自动驾驶技术中定位担负着相当重要的职责。车辆自身定位信息获取的方式多样,涉及多种传感器类型与相关技术。自动驾驶汽车能够持续安全可靠运行的一个关键前提是车辆的定位系统必须实时…...

数据结构 | 基本数据结构——队列
目录 一、何谓队列 二、队列抽象数据类型 三、用Python实现队列 四、模拟:传土豆 五、模拟:打印任务 5.1 主要模拟步骤 5.2 Python实现 一、何谓队列 队列是有序集合,添加操作发生在“尾部”,移除操作则发生在“头部”。新…...
QT在label上透明绘图(二)
前面步骤参考前一篇文章 QT在label上透明绘图 一、给TransparentLabel类添加double transparency;变量, 二、ui添加doublespinbox,调整透明参数 void MainWindow::on_doubleSpinBox_valueChanged(double arg1) {transparentLabel->transparencyarg1;…...

微信小程序使用editor富文本编辑器 以及回显 全屏弹窗的模式
<!--富文本接收的位置--><view class"white-box"><view class"title"><view class"yellow-fence"></view><view class"v1">教研记录</view></view><view class"add-btn"…...
在CSDN学Golang场景化解决方案(基于gin框架的web开发脚手架)
一,中间件统一实现Oauth2身份验证 在Golang基于Gin框架开发Web应用程序时,可以使用gin-oauth2来实现Oauth2身份验证。下面是简单的步骤: 安装gin-oauth2包:go get github.com/appleboy/gin-oauth2导入依赖:import &q…...

关于Express 5
目录 1、概述 2、Express 5的变化 2.1 弃用或删除内容的列表: app.param(name,fn)名称中的前导冒号(:) app.del() app.param(fn) 复数方法名 res.json࿰…...
ftrace 原理详细分析
》内核新视界文章汇总《 文章目录 ftrace 原理分析1 简介2 ftrace 的编译器支持2.1 HAVE_FUNCTION_TRACER 选项对 ftrace 的支持2.2 HAVE_DYNAMIC_FTRACE 选项对动态 ftrace 的支持 3 ftrace 的初始化4 function trace 流程5 总结 ftrace 原理分析 1 简介 ftrace 是一个内核…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...

Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)
UniApp 集成腾讯云 IM 富媒体消息全攻略(地理位置/文件) 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型,核心实现方式: 标准消息类型:直接使用 SDK 内置类型(文件、图片等)自…...
华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...