设计模式--享元模式
享元模式(Flyweight Pattern)是一种结构型设计模式,它通过共享大量细粒度的对象来减少内存消耗。这个模式的核心思想是把对象的状态分为内在状态和外在状态,其中内在状态是可以共享的,而外在状态是需要独立维护的。
享元模式的结构
享元模式主要包含以下几个部分:
-
享元接口(Flyweight Interface):定义了具体享元类需要实现的方法。这些方法主要用于操作享元对象的内在状态。
-
具体享元类(Concrete Flyweight):实现享元接口,并存储可以共享的内在状态。
-
非共享享元类(Unshared Flyweight):并不是所有的享元对象都可以共享,对于那些不能共享的享元对象,可以通过这个类来实现。
-
享元工厂类(Flyweight Factory):负责创建和管理享元对象,并确保合理地共享这些对象。
-
客户端(Client):使用享元模式的类。客户端需要将外在状态传递给享元对象。
享元模式的实现
以下是一个简单的享元模式示例,用于管理和共享一些图形对象,如圆形。
// 享元接口
interface Shape {void draw(String color);
}// 具体享元类
class Circle implements Shape {private String intrinsicState; // 内在状态,可以共享private String extrinsicState; // 外在状态,每个对象独有public Circle(String intrinsicState) {this.intrinsicState = intrinsicState;}@Overridepublic void draw(String color) {this.extrinsicState = color;System.out.println("Drawing Circle with color: " + color + " and intrinsic state: " + intrinsicState);}
}// 享元工厂类
class ShapeFactory {private static final Map<String, Shape> circleMap = new HashMap<>();public static Shape getCircle(String intrinsicState) {Circle circle = (Circle) circleMap.get(intrinsicState);if (circle == null) {circle = new Circle(intrinsicState);circleMap.put(intrinsicState, circle);System.out.println("Creating circle with intrinsic state: " + intrinsicState);}return circle;}
}// 客户端
public class FlyweightPatternDemo {public static void main(String[] args) {Shape circle1 = ShapeFactory.getCircle("Shared State 1");circle1.draw("Red");Shape circle2 = ShapeFactory.getCircle("Shared State 1");circle2.draw("Green");Shape circle3 = ShapeFactory.getCircle("Shared State 2");circle3.draw("Blue");}
}
在这个示例中,Circle
类实现了 Shape
接口,并包含了内在状态(intrinsicState
)和外在状态(extrinsicState
)。ShapeFactory
类通过管理一个 HashMap
来共享 Circle
对象。客户端通过 ShapeFactory
获取 Circle
对象,并传递外在状态来绘制图形。
对象的状态分为内在状态和外在状态
将对象的状态分为内在状态和外在状态是享元模式的核心概念之一。内在状态是对象内部固有的、不随环境改变的状态,而外在状态是依赖于环境、可以在对象外部改变的状态。
为了更好地理解这个概念,我们可以通过一个例子来解释。
示例:围棋棋子
假设我们要实现一个围棋游戏,其中有许多棋子。这些棋子只有黑白两种颜色,但每个棋子的位置(行和列)是不同的。我们可以通过享元模式来共享棋子的颜色(内在状态),而位置(外在状态)则由客户端提供。
// 享元接口
interface GoPiece {void place(int row, int col);
}// 具体享元类
class GoPieceImpl implements GoPiece {private String color; // 内在状态public GoPieceImpl(String color) {this.color = color;}@Overridepublic void place(int row, int col) {System.out.println("Placing " + color + " piece at (" + row + ", " + col + ")");}
}// 享元工厂类
class GoPieceFactory {private static final Map<String, GoPiece> pieces = new HashMap<>();public static GoPiece getGoPiece(String color) {GoPiece piece = pieces.get(color);if (piece == null) {piece = new GoPieceImpl(color);pieces.put(color, piece);System.out.println("Creating " + color + " piece.");}return piece;}
}// 客户端
public class FlyweightPatternDemo {public static void main(String[] args) {GoPiece blackPiece1 = GoPieceFactory.getGoPiece("Black");blackPiece1.place(1, 1);GoPiece blackPiece2 = GoPieceFactory.getGoPiece("Black");blackPiece2.place(2, 2);GoPiece whitePiece1 = GoPieceFactory.getGoPiece("White");whitePiece1.place(1, 2);GoPiece whitePiece2 = GoPieceFactory.getGoPiece("White");whitePiece2.place(2, 1);}
}
在这个示例中:
- 内在状态:棋子的颜色(
color
)是可以共享的,这个状态是固定的,不会因为棋子的位置而改变。因此,我们将颜色设为内在状态。 - 外在状态:棋子的行和列(
row
和col
)是随时变化的,这个状态取决于棋子在棋盘上的具体位置。因此,我们将位置设为外在状态,由客户端在使用棋子时传递。
在享元模式中,通过将内在状态和外在状态分离,我们可以显著减少内存消耗。在上述示例中,我们只创建了两个享元对象(黑棋子和白棋子),即使我们在不同位置放置了多个棋子,也只是复用这两个享元对象。
享元模式的优缺点
优点
- 减少内存消耗:通过共享细粒度对象,可以显著减少内存使用,适用于大量重复对象的场景。
- 提高性能:由于减少了对象的创建和销毁,可以提高系统的性能。
缺点
- 复杂性增加:引入享元模式后,系统的复杂性增加,需要额外的代码来管理共享对象。
- 适用场景有限:享元模式并不适用于所有场景,只有在有大量细粒度对象需要共享时才适用。
适用场景
享元模式主要适用于以下场景:
- 系统中有大量相似对象,造成了内存的高消耗。
- 大部分对象的状态是可以外部化的,可以通过外在状态来区分对象。
- 对象的内在状态是相对稳定且不变的。
通过享元模式,可以在保证系统性能的前提下,有效地减少内存的使用,提高系统的可扩展性。
相关文章:
设计模式--享元模式
享元模式(Flyweight Pattern)是一种结构型设计模式,它通过共享大量细粒度的对象来减少内存消耗。这个模式的核心思想是把对象的状态分为内在状态和外在状态,其中内在状态是可以共享的,而外在状态是需要独立维护的。 享…...

可视化剪辑,账号矩阵,视频分发,聚合私信一体化营销工具 源----代码开发部署方案
可视化剪辑: 为了实现可视化剪辑功能,可以使用流行的视频编辑软件或者开发自己的视频编辑工具。其中,通过设计用户友好的界面,用户可以简单地拖拽和放大缩小视频片段,剪辑出满足需求的视频。在开发过程中,可…...
CCF-CSP认证考试 202406-2 矩阵重塑(其二) 100分题解
更多 CSP 认证考试题目题解可以前往:CSP-CCF 认证考试真题题解 原题链接: 202406-2 矩阵重塑(其二) 时间限制: 1.0 秒 空间限制: 512 MiB 题目背景 矩阵转置操作是将矩阵的行和列交换的过程。在转置过程…...

初阶数据结构的实现1 顺序表和链表
顺序表和链表 1.线性表1.1顺序表1.1.1静态顺序表(不去实现)1.1.2动态顺序表1.1.2.1 定义程序目标1.1.2.2 设计程序1.1.2.3编写代码1.1.2.3测试和调试代码 1.1.2 顺序表的问题与思考 1.2链表1.2.1链表的概念及结构1.2.1.1 定义程序目标1.2.1.2 设计程序1.…...

破解反爬虫策略 /_guard/auto.js(一) 原理
背景 当用代码或者postman访问一个网站的时候,访问他的任何地址都会返回<script src"/_guard/auto.js"></script>,但是从浏览器中访问显示的页面是正常的,这种就是网站做了反爬虫策略。本文就是带大家来破解这种策略&…...

40.简易频率计(基于等精度测量法)(3)
(1)BCD8421码:十进制数字转换成BCD8421码的方法 补零:你需要显示多少位数字,就在前面补上四倍的位宽。比如你要显示一个十进制8位的数字,就在前面补上8*432个零。判断:判断补零部分显示的十进制…...

关于Centos停更yum无法使用的解决方案
最近在使用Centos7.9系统时候,发现yum仓库无法进行安装软件包了,官方说2024年6月30日进行停更,停更后无法提供对应的软件服务。 我在使用yum安装包的时候发现确实不能使用官方服务了: CentOS停更的影响 CentOS停止更新之后&#…...

插画感言:成都亚恒丰创教育科技有限公司
插画感言:笔触间的灵魂对话 在这个快节奏、高压力的时代,我们时常在寻找那些能够触动心灵、让灵魂得以片刻栖息的角落。而插画,这一融合了艺术与情感的独特形式,便如同一股清泉,缓缓流淌进每个人的心田,以…...
【算法】数组中的第K个最大元素
难度:中等 题目: 给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。 请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。 你必须设计并实现时间复杂度为 O(n) 的算法解决此问题…...
Perl 语言的特点
Perl 语言入门学习可以涵盖多个方面,包括其特点、基本语法、高级特性以及学习资源和社区支持等。以下是一个详细的入门学习指南: 一、Perl 语言的特点 文本处理能力强:Perl 提供了丰富的字符串处理函数和正则表达式的支持,非常适…...

NLP教程:1 词袋模型和TFIDF模型
文章目录 词袋模型TF-IDF模型词汇表模型 词袋模型 文本特征提取有两个非常重要的模型: 词集模型:单词构成的集合,集合自然每个元素都只有一个,也即词集中的每个单词都只有一个。 词袋模型:在词集的基础上如果一个单词…...

【开源 Mac 工具推荐之 2】洛雪音乐(lx-music-desktop):免费良心的音乐平台
旧版文章:【macOS免费软件推荐】第6期:洛雪音乐 Note:本文在旧版文章的基础上,新更新展示了一些洛雪音乐的新功能,并且描述更为详细。 简介 洛雪音乐(GitHub 名:lx-music-desktop )…...

AMEYA360:思瑞浦推出汽车级理想二极管ORing控制器TPS65R01Q
聚焦高性能模拟芯片和嵌入式处理器的半导体供应商思瑞浦3PEAK(股票代码:688536)发布汽车级理想二极管ORing控制器TPS65R01Q。 TPS65R01Q拥有20mV正向调节功能,降低系统损耗。快速反向关断(Typ:0.39μs),在电池反向和各种汽车电气瞬…...

简约的悬浮动态特效404单页源HTML码
源码介绍 简约的悬浮动态特效404单页源HTML码,页面简约美观,可以做网站错误页或者丢失页面,将下面的代码放到空白的HTML里面,然后上传到服务器里面,设置好重定向即可 效果预览 完整源码 <!DOCTYPE html> <html><head><meta charset="utf-8&q…...
Golang 创建 Excel 文件
经常会遇到需要导出数据报表的需求,除了可以通过 encoding/csv 导出 CSV 以外,还可以使用 https://github.com/qax-os/excelize 导出 xlsx 等格式的 excel,下面封装了一个方法,支持多 sheet 的 excel 数据生成,导出按需…...

探索GitHub上的两个革命性开源项目
在数字世界中,总有一些项目能够以其创新性和实用性脱颖而出,吸引全球开发者的目光。今天,我们将深入探索GitHub上的两个令人惊叹的开源项目:Comic Translate和GPTPDF,它们不仅改变了我们处理信息的方式,还极…...

SpringBoot框架学习笔记(三):Lombok 和 Spring Initailizr
1 Lombok 1.1 Lombok 介绍 (1)Lombok 作用 简化JavaBean开发,可以使用Lombok的注解让代码更加简洁Java项目中,很多没有技术含量又必须存在的代码:POJO的getter/setter/toString;异常处理;I/O…...
【ASP.NET网站传值问题】“object”不包含“GetEnumerator”的公共定义,因此 foreach 语句不能作用于“object”类型的变量等
问题一:不允许遍历 原因:实体未强制转化 后端: ViewData["CateGroupList"] grouplist; 前端加上:var catelist ViewData["CateGroupList"] as List<Catelogue>; 这样就可以遍历catelist了 问题二:…...

Stateflow中的状态转换表
状态转换表是表达顺序模态逻辑的另一种方式。不要在Stateflow图表中以图形方式绘制状态和转换,而是使用状态转换表以表格格式表示模态逻辑。 使用状态转换表的好处包括: 易于对类列车状态机进行建模,其中模态逻辑涉及从一个状态到其邻居的转换…...
结合Redis解决接口幂等性问题
结合Redis解决接口幂等性问题 引言正文收获 引言 该问题产生背景是根据需求描述,要求对已发布的课程能进行编辑修改,并且要求能进行回滚。 幂等性问题描述:对同一个接口并发请求产生的结果是不变的。 Get 请求以及 Delete 请求天然保证幂等…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...

华为OD机试-食堂供餐-二分法
import java.util.Arrays; import java.util.Scanner;public class DemoTest3 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的区别while (in.hasNextLine()) { // 注意 while 处理多个 caseint a in.nextIn…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...