享元模式(Flyweight Pattern)
享元模式(Flyweight Pattern)
定义
享元模式通过共享技术来支持大量细粒度的对象,以减少内存中的对象数量。其核心思想是将对象的状态分为内部状态和外部状态,内部状态是不变的,可以被多个对象共享;外部状态是随环境改变而改变的,不能共享,必须由客户端保持。
属于结构型模式。
适用场景
- 系统有大量相似对象:这些对象除了几个参数外基本相同,可以通过共享来减少内存消耗。
- 需要缓冲池的场景:如数据库连接池、线程池等,通过共享对象池中的对象来提高资源利用率。
- 对象创建成本较高:创建对象的成本较高时,使用享元模式可以减少对象的创建数量,降低成本。
标准示例

Flyweight 抽象的享元角色
这是所有具体享元类的超类,为这些类规定出需要实现的公共接口。通常包含一些与内部状态相关的操作,这些内部状态是可以在多个享元对象之间共享的。
/*** 抽象享元角色*/
public interface IFlyweight {/*** 业务方法* @param extrinsicState 外在状态*/void operation(String extrinsicState);
}
ConcreteFlyweight 具体的享元角色
实现抽象享元角色所规定的接口。如果有内部状态的话,必须负责为内部状态提供存储空间。享元对象的内部状态必须与对象所处的周围环境无关,从而使得享元对象可以在系统内共享的。
/*** 具体享元角色*/
public class ConcreteFlyweight implements IFlyweight{//内在状态,内在状态不会改变private String intrinsicState;public ConcreteFlyweight(String intrinsicState){this.intrinsicState = intrinsicState;}/*** 业务方法* @param extrinsicState 外在状态*/public void operation(String extrinsicState) {System.out.println("Object address:" + System.identityHashCode(this));System.out.println("IntrinsicState:" + this.intrinsicState);System.out.println("ExtrinsicState:" + extrinsicState);}
}
FlyweightFactory 享元工厂角色
负责创建和管理享元角色。当客户端请求一个享元对象时,享元工厂会检查系统中是否已经存在适当的享元对象,如果存在则直接返回该对象,否则创建一个新的享元对象。
通常通过哈希表(如HashMap)来存储和管理享元对象,以提高对象的检索和创建效率。
/*** 享元工厂*/
public class FlyweightFactory {private static Map<String,IFlyweight> pool = new HashMap<String, IFlyweight>();//内部状态作为缓存的keypublic static IFlyweight getFlyweight(String intrinsicState){if (!pool.containsKey(intrinsicState)){IFlyweight flyweight = new ConcreteFlyweight(intrinsicState);pool.put(intrinsicState,flyweight);}return pool.get(intrinsicState);}
}
ClientTest 调用类:
public class ClientTest {public static void main(String[] args) {IFlyweight flyweight = FlyweightFactory.getFlyweight("黑桃A");flyweight.operation("地主出的");IFlyweight flyweight1 = FlyweightFactory.getFlyweight("黑桃A");flyweight1.operation("地主出过的");}
}
执行结果输出为:
Object address:1360875712
IntrinsicState:黑桃A
ExtrinsicState:地主出的
Object address:1360875712
IntrinsicState:黑桃A
ExtrinsicState:地主出过的
内部状态与外部状态:
享元模式的关键在于区分内部状态和外部状态。
内部状态是可以在多个对象中共享的,而外部状态是随环境改变而改变的,不能共享。
举一个下五子棋的例子。
棋子的颜色为内部状态:黑和白;
下棋坐标位置为外部状态:Point(x,y)
假设一局五子棋,黑白双方各落子30枚,如果不用享元,就要new 60个对象。
如果采用享元,只需要2个对象即可。
请看如下设计:
ChessPiece 棋子,作为抽象享元角色,包含了一个落子的方法 placingPiece(Point p)
/*** 抽象棋子*/
public interface ChessPiece {/*** 落子* @param point 落子坐标*/void placingPiece(Point point);
}
WhitePiece 白色棋子,是具体享元角色。
/*** 白色棋子*/
public class WhitePiece implements ChessPiece{private String color = "white";public void placingPiece(Point point) {System.out.println( color +" piece named "+System.identityHashCode(this) + ", placing on "+point.toString());}
}
BlackPiece 黑色棋子,是具体享元角色。
/*** 黑色棋子*/
public class BlackPiece implements ChessPiece{private String color = "black";public void placingPiece(Point point) {System.out.println( color +"piece named "+System.identityHashCode(this) + ", placing on "+point.toString());}
}
Point 是非享元角色,即外部状态。
/*** 棋盘坐标点*/
@Data
public class Point {private String x;private String y;public Point(String x,String y){this.x = x;this.y = y;}@Overridepublic String toString() {return "" +"x='" + x + '\'' +", y='" + y + '\'';}
}
GobangFactory 五子棋工厂,用来提供棋子。
/*** 五子棋工厂类*/
public class GobangFactory {private static Map<String,ChessPiece> pieces = new HashMap<String, ChessPiece>(2);public static ChessPiece getPiece(String color){if(!StringUtils.equalsAny(color,"black","white")){throw new UnsupportedOperationException("拿错棋子了!");}//如果map中还没有棋子,那么添加进去。if(!pieces.containsKey(color)){//如果是白色,就把白子加进mapif("white".equals(color)){ChessPiece piece =new WhitePiece();pieces.put("white",piece);}//如果是黑色,就把黑子加进mapif("black".equals(color)){ChessPiece piece =new BlackPiece();pieces.put("black",piece);}}//取子返回return pieces.get(color);}}
ClientPlay 调用类:
public class ClientPlay {public static void main(String[] args) {ChessPiece piece1 = GobangFactory.getPiece("white");piece1.placingPiece(new Point("10","20"));ChessPiece piece2 = GobangFactory.getPiece("black");piece2.placingPiece(new Point("10","30"));ChessPiece piece3 = GobangFactory.getPiece("white");piece3.placingPiece(new Point("20","40"));ChessPiece piece4 = GobangFactory.getPiece("black");piece4.placingPiece(new Point("20","50"));}
}
执行结果输出为:
white piece named 1725154839, placing on x='10', y='20'
blackpiece named 1670675563, placing on x='10', y='30'
white piece named 1725154839, placing on x='20', y='40'
blackpiece named 1670675563, placing on x='20', y='50'
以上为享元模式全部内容,感谢阅读。
相关文章:
享元模式(Flyweight Pattern)
享元模式(Flyweight Pattern) 定义 享元模式通过共享技术来支持大量细粒度的对象,以减少内存中的对象数量。其核心思想是将对象的状态分为内部状态和外部状态,内部状态是不变的,可以被多个对象共享;外部状…...
Oracle连接mysql
oracle使用的11g,在一台windows服务器;mysql使用的是5.7版本,在另一台windows服务器,这两个服务器之间的网络是互通的。做BI时,要获取不同数据源的数据,这些数据源可能是Oracle,也可能是sqlserv…...
golang 垃圾回收
gc不回收什么 GC 不负责回收栈中的内存栈是一块专用内存,专门为了函数执行而准备的,存储着函数中的局部变量以及调用栈栈中的数据可以通过简单的编译器指令自动清理,也就不需要通过 GC 来回收了 垃圾回收算法 主流的两类垃圾回收算法有两种&a…...
React 中如何使用 Monaco
Monaco 是微软开源的一个编辑器,VSCode 也是基于 Monaco 进行开发的。如果在 React 中如何使用 Monaco,本文将介绍如何在 React 中引入 Monaco。 安装 React 依赖 yarn add react-app-rewired --dev yarn add monaco-editor-webpack-plugin --dev yarn…...
开源RAG个人知识库项目开发分析
前言 Hello,大家好,我是GISer Liu😁,一名热爱AI技术的GIS开发者,这个LLM开发基础阶段已经进入尾声了,本文中我们不介绍更多的理论与知识点,而是通过的分析开源项目的解决方案来帮助各位开发者理…...
事务底层与高可用原理
1.事务底层与高可用原理 事务的基础知识 mysql的事务分为显式事务和隐式事务 默认的事务是隐式事务 显式事务由我们自己控制事务的开启,提交,回滚等操作 show variables like autocommit; 事务基本语法 事务开始 1、begin 2、START TRANSACTION&…...
树状数组基础知识
lowbit: lowbit(x)x&(-x) 树状数组: 树状数组的功能: 数组 在O(1)的时间复杂度实现单点加: 在O(lng n)的时间复杂度实现查询前缀和: 树状数组的定义: 查询前x项的和操作: ll query(int x){ll s0;f…...
【3分钟准备前端面试】vue3
目录 Vue3比vue2有什么优势vue3升级了哪些重要功能生命周期变化Options APIComposition APIreftoRef和toRefstoReftoRefsHooks (代码复用)Vue3 script setupsetupdefineProps和defineEmitsdefineExposeVue3比vue2有什么优势 性能更好体积更小更好的TS支持更好的代码组织更好的逻…...
【数据采集】亮数据浏览器、亮网络解锁器实战指南
前言 继上次我们写了数据采集与AI分析,亮数据通义千问助力跨境电商前行的文章之后,好多小伙伴来后台留言,表示对亮数据的数据采集非常感兴趣,并且感觉用起来非常顺手,大大减少了小白用户获取数据的成本。 在这儿&…...
暑期编程预习指南
暑期编程预习指南 高考结束后,迎来的是一段难得的假期时光。对于那些有志于踏入IT领域的高考生来说,这段时间无疑是一个重要的起点。为了帮助你们更好地利用这个假期,为未来的学习和职业生涯打下坚实的基础,特此提供一份编程预习…...
将带有 商店idr 商品信息的json导入到mongodb后,能不能根据商店id把所有商品全部提取并转为电子表格
当您已经将包含商店ID(如realMallId)的商品信息导入MongoDB后,确实可以轻松地根据商店ID提取所有相关商品信息并转换为电子表格(例如Excel)。这里是一个简化的流程,使用Python的pymongo库来查询MongoDB&…...
深入解析 androidx.databinding.BaseObservable
在现代 Android 开发中,数据绑定 (Data Binding) 是一个重要的技术,它简化了 UI 和数据之间的交互。在数据绑定框架中,androidx.databinding.BaseObservable 是一个关键类,用于实现可观察的数据模型。本文将详细介绍 BaseObservab…...
MySQL数据恢复(适用于误删后马上发现)
首先解释一下标题,之所以适用于误删后马上发现是因为太久了之后时间和当时操作的数据表可能会记不清楚,不是因为日志丢失 1.首先确保自己的数据库开启了binlog(我的是默认开启的我没有配置过) 根据这篇博客查看自己的配置和自己…...
[数据结构】——七种常见排序
文章目录 前言 一.冒泡排序二.选择排序三.插入排序四.希尔排序五.堆排序六.快速排序hoare挖坑法前后指针快排递归实现:快排非递归实现: 七、归并排序归并递归实现:归并非递归实现: 八、各个排序的对比图 前言 排序:所谓…...
CPU占用率飙升至100%:是攻击还是正常现象?
在运维和开发的日常工作中,CPU占用率突然飙升至100%往往是一个令人紧张的信号。这可能意味着服务器正在遭受攻击,但也可能是由于某些正常的、但资源密集型的任务或进程造成的。本文将探讨如何识别和应对服务器的异常CPU占用情况,并通过Python…...
java如何替换字符串中给定索引的字符
java如果要修改给定字符串的索引字符,需要用到setCharAt方法 它的语法格式是 sbf.setCharAt(index,ch) 其中: sbf是任意StringBuffer对象 index是被替换字符的索引 ch是替换后的索引 如果是修改一个字符就用这个方法。如果是批量修改,…...
基于RK3588的GMSL、FPDLink 、VByone及MIPI等多种摄像模组,适用于车载、机器人工业图像识别领域
机器人&工业摄像头 针对机器人视觉与工业检测视觉,信迈自主研发和生产GMSL、FPDLink 、VByone及MIPI等多种摄像模组,并为不同应用场景提供多种视场角度和镜头。拥有资深的图像算法和图像ISP专家团队,能够在软件驱动层开发、ISP算法、FPG…...
Windows 的 MFC开发的使用示例——讲得挺好的
【Visual Studio 2019】创建 MFC 桌面程序 ( 安装 MFC 开发组件 | 创建 MFC 应用 | MFC 应用窗口编辑 | 为按钮添加点击事件 | 修改按钮文字 | 打开应用 )-腾讯云开发者社区-腾讯云 (tencent.com)...
Spring4.3.x xml配置文件搜索和解析过程
###概述 这篇文章的研究不只是涉及到spring如何创建一个BeanDefinition对象,还涉及到spring如何加载文件、如何读取XML文件、以及我们在使用spring的时候如何扩展spring的配置。 spring在创建BeanFactory时会把xml配置文件和注解信息转换为一个个BeanDefinition对…...
网络爬虫(一)深度优先爬虫与广度优先爬虫
1. 深度优先爬虫:深度优先爬虫是一种以深度为优先的爬虫算法。它从一个起始点开始,先访问一个链接,然后再访问该链接下的链接,一直深入地访问直到无法再继续深入为止。然后回溯到上一个链接,再继续深入访问下一个未被访…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...
使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...
江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
深度学习水论文:mamba+图像增强
🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...
