享元(轻量级)模式
简介
享元模式(Flyweight Pattern)又叫作轻量级模式,是对象池的一种实现。类似线程池,线程池可以避免不停地创建和销毁多个对象,消耗性能。享元模式提供了减少对象数量从而改善应用所需的对象结构的方式。其宗旨是共享细粒度对象,将多个对同一对象的访问集中起来,不必为每个访问者都创建一个单独的对象,以此来降低内存的消耗,属于结构型设计模式。
享元(Flyweight)的核心思想很简单:如果一个对象实例一经创建就不可变,那么反复创建相同的实例就没有必要,直接向调用方返回一个共享的实例就行,这样即节省内存,又可以减少创建对象的过程,提高运行速度。
通用模板
-
创建抽象享元角色:享元对象抽象基类或者接口。
// 享元接口 public interface IFlyweight {void operation(String extrinsicState); }
-
创建具体享元角色:实现抽象角色定义的业务。
// 具体的享元角色 public class FlyWeight implements IFlyweight {private String intrinsicState;public FlyWeight(String intrinsicState) {this.intrinsicState = intrinsicState;}@Overridepublic void operation(String extrinsicState) {System.out.println("Object address: " + System.identityHashCode(this));System.out.println("IntrinsicState: " + this.intrinsicState);System.out.println("ExtrinsicState: " + extrinsicState);} }
-
创建享元工厂::负责管理享元对象池和创建享元对象。
import java.util.HashMap; import java.util.Map; // 享元工厂 public class FlyweightFactory {private static Map<String, IFlyweight> pool = new HashMap<String, IFlyweight>();// 因为内部状态具备不变性,因此作为缓存的键public static IFlyweight getFlyweight(String intrinsicState) {if (!pool.containsKey(intrinsicState)) {IFlyweight flyweight = new FlyWeight(intrinsicState);pool.put(intrinsicState, flyweight);}return pool.get(intrinsicState);} }
模板测试
-
代码
public class Client {public static void main(String[] args) {IFlyweight flyweight1 = FlyweightFactory.getFlyweight("aa");IFlyweight flyweight2 = FlyweightFactory.getFlyweight("aa");flyweight1.operation("aa");flyweight2.operation("b");} }
-
结果
Object address: 2133927002 IntrinsicState: aa ExtrinsicState: aa Object address: 2133927002 IntrinsicState: aa ExtrinsicState: b
内部状态和外部状态
享元模式的定义提出了两个要求:细粒度和共享对象。因为要求细粒度,所以不可避免地会使对象数量多且性质相近,此时我们就将这些对象的信息分为两个部分:内部状态和外部状态。
内部状态指对象共享出来的信息,存储在享元对象内部,并且不会随环境的改变而改变;外部状态指对象得以依赖的一个标记,随环境的改变而改变,不可共享。
比如,连接池中的连接对象,保存在连接对象中的用户名、密码、连接URL等信息,在创建对象的时候就设置好了,不会随环境的改变而改变,这些为内部状态。而当每个连接要被回收利用时,我们需要将它标记为可用状态,这些为外部状态。
应用场景
在生活中,享元模式非常常见,比如各中介机构的房源共享,再比如全国社保联网。 当系统中多处需要同一组信息时,可以把这些信息封装到一个对象中,然后对该对象进行缓存,这样,一个对象就可以提供给多处需要使用的地方,避免大量同一对象的多次创建,降低大量内存空间的消耗。 享元模式其实是工厂方法模式的一个改进机制,享元模式同样要求创建一个或一组对象,并且就是通过工厂方法模式生成对象的,只不过享元模式为工厂方法模式增加了缓存这一功能。主要应用场景如下。 (1)常应用于系统底层的开发,以便解决系统的性能问题。
(2)系统有大量相似对象、需要缓冲池的场景。
优点
(1)减少对象的创建,降低内存中对象的数量,降低系统的内存,提高效率。
(2)减少内存之外的其他资源占用。
缺点
(1)关注内、外部状态,关注线程安全问题。
(2)使系统、程序的逻辑复杂化。
“生搬硬套”实战
场景描述
一个典型的享元模式的应用场景是在处理大量细粒度对象时,比如在一个文字处理软件中表示文档中的字符。如果每个字符都作为一个独立的对象创建,那么对于一个包含数千字符的文档来说,将会有大量的对象被创建,这会消耗大量的内存。使用享元模式可以有效地减少内存使用,因为相同的字符可以被多个位置共享。
代码开发
根据模板我们知道抽象工厂和工厂方法模式一样也是拢共就是3步:
-
创建抽象享元角色(这里指的是字符享元接口)
// 字符享元接口 public interface ICharFlyweight {// 展示字符位置的方法void display(int position); }
-
创建具体享元角色(这里指的是字符对象的具体类)
// 具体的字符享元实现 public class ConcreteCharFlyweight implements ICharFlyweight {private final char character;public ConcreteCharFlyweight(char character) {this.character = character;}@Overridepublic void display(int position) {System.out.println("Displaying '" + character + "' at position " + position);} }
-
创建享元工厂(这里指的是创建字符对象的工厂)
// 创建字符对象的工厂,如果字符对象已经存在,则直接使用,否则存储起来备用 public class FlyweightFactory {private static final Map<Character, ICharFlyweight> pool = new HashMap<Character, ICharFlyweight>();public static ICharFlyweight getCharFlyweight(char character) {ICharFlyweight flyweight = pool.get(character);if (flyweight == null) {flyweight = new ConcreteCharFlyweight(character);pool.put(character, flyweight);}return flyweight;} }
至此,我们就通过“生搬硬套”享元模式的模板设计出一套对象池开发流程,接下来我们进行测试:
-
测试代码
public class Demo {public static void main(String[] args) {String text = "Hello World!";for (int i = 0; i < text.length(); i++) {char c = text.charAt(i);ICharFlyweight flyweight = FlyweightFactory.getCharFlyweight(c);flyweight.display(i);}} }
-
结果
Displaying 'H' at position 0 Displaying 'e' at position 1 Displaying 'l' at position 2 Displaying 'l' at position 3 Displaying 'o' at position 4 Displaying ' ' at position 5 Displaying 'W' at position 6 Displaying 'o' at position 7 Displaying 'r' at position 8 Displaying 'l' at position 9 Displaying 'd' at position 10 Displaying '!' at position 11
这样每当有已经出现过的字符出现,则复用对象。
总结
享元模式的本质是缓存共享对象,降低内存消耗。
相关文章:
享元(轻量级)模式
简介 享元模式(Flyweight Pattern)又叫作轻量级模式,是对象池的一种实现。类似线程池,线程池可以避免不停地创建和销毁多个对象,消耗性能。享元模式提供了减少对象数量从而改善应用所需的对象结构的方式。其宗旨是共享…...

基于php的幸运舞蹈课程工作室管理系统
作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏:Java精选实战项目…...
NLP任务的详细原理与步骤的详细讲解
1. 文本分类 原理: 特征提取:文本分类首先将文本转化为数值特征,常用方法包括词袋模型、TF-IDF、Word Embeddings(如Word2Vec、GloVe)和BERT等预训练模型。模型训练:模型(如SVM、神经网络&…...

Kotlin 处理字符串和正则表达式(二十一)
导读大纲 1.1 处理字符串和正则表达式1.1.1 分割字符串1.1.2 正则表达式和三引号字符串1.1.3 多行三引号字符串IntelliJ IDEA 和 Android Studio 中三重引号字符串内部的语法高亮显示 1.1 处理字符串和正则表达式 Kotlin 字符串与 Java 字符串完全相同 可以将 Kotlin 代码中创建…...

一站式大语言模型API调用:快速上手教程
智匠MindCraft是一个强大的AI工具及开发平台,支持多种大语言模型和多模态AI模型。本文将详细介绍如何通过API调用智匠MindCraft中的大语言模型,帮助开发者快速上手。 注册与登录 访问智匠MindCraft官网,注册并登录账号。 进入开发者平台&…...

【TabBar嵌套Navigation案例-新特性页面-代码位置 Objective-C语言】
一、接下来,我们来说这个新特性页面 1.首先,看一下我们的示例程序,这里改一下,加一个叹号, command + R, 好,首先啊,这里边有一个新特性页面,当我这个程序是第一次安装、第一次运行、还有呢、就是当这个应用程序更新的时候,我应该去加载这个新特性页面, 然后呢,这…...
程序员如何提升并保持核心竞争力?——深入钻研、广泛学习与软技能的培养
一、引言 随着人工智能的不断发展,尤其是AIGC系列大语言模型的涌现,AI辅助编程工具正在日益普及,这对程序员的工作方式产生了深刻的影响。面对这一变革,程序员应如何应对?是专注于某个领域深耕细作,还是…...

Linux之Docker虚拟化部署
上传docker安装包 解压安装包 将解压后的docker文件夹移动到/usr/local/文件夹下 docker 启动命令/usr/local/docker/dockerd 但是启动报错,意思是没有docker用户组 创建docker用户组,执行完会生成套接字文件 将套接字文件加入该用户组管理 第二个错误原…...

重构部队信息安全:部队涉密载体建设新策略
一、完善保密体系架构 1. 加强保密规章制度:制定或刷新关于机密信息管理的相关规定,明确机密信息的生成、复制、传输、使用、储存及销毁等核心环节的操作准则与责任分配,确保整个流程的标准化运作。 2. 明确个人保密义务:通过保密…...
使用Node.js的readline模块逐行读取并解析大文件
在Node.js环境中处理大文件是一个常见的需求,尤其是在处理日志文件、数据库导出、或任何形式的大规模文本数据时。由于Node.js是基于事件循环和非阻塞I/O的,它非常适合处理这类任务。然而,直接将整个文件内容加载到内存中可能会导致内存溢出&…...
浅谈软件安全开发的重要性及安全开发实践
在当今数字化时代,软件已成为企业运营的核心驱动力。然而,随着网络环境的日益复杂和黑客技术的不断演进,软件安全问题日益凸显,成为企业不可忽视的重大挑战。本文将从法律法规要求、企业核心数据资产保护、企业信誉等角度…...
在 NodeJs 里面如何获取 APK 的名称和 icon
最近想用 electron 写一个 adb 的可视化客户端,在展示安装的应用时遇到了如何获取 APK 的名称和 icon 的问题。下面就是一些解决问题的思路。 前提:在这里默认大家已经下载好 apk, 下面 localApkPath 就是你下载好的 apk 的路径。 小提示,示…...

基于VirtualBox和Ubuntu的虚拟环境搭建
VirtualBox简介 VirtualBox 是一款开源虚拟机软件。 是由德国 Innotek 公司开发,由Sun Microsystems公司出品的软件,使用Qt编写,在 Sun 被 Oracle 收购后正式更名成 Oracle VM VirtualBox。简单易用,可虚拟的系统包括Windows&…...

【PHP源码】匿名来信系统H5版本V1.0免费开源
你的匿名来信H5一封你的来信源码/表白祝福短信程序/往来信/传话短信源码支持邮件发信与手机短信发信“你的匿名来信”是最近某音上爆火的一个活动话题,可以通过H5网站,编辑自己想要对某人说的话或者祝福,网站会把您想说的发给您预留的号码&am…...
Prompt技巧总结和示例分享
"Prompt"(提示)在人工智能中通常指的是输入给模型的文本,用于引导模型生成预期的输出。在使用人工智能助手时,有效的提示技巧可以帮助你获得更准确和有用的回答。 以下是一些单轮对话提示时的技巧: 明确具体…...
大厂校招:海能达嵌入式面试题及参考答案
SPI 协议的一些基础知识 SPI(Serial Peripheral Interface)即串行外设接口,是一种高速的、全双工、同步的通信总线。 SPI 主要由四根信号线组成: 时钟线(SCLK):由主设备产生,用于同步数据传输。时钟的频率决定了数据传输的速度。主设备输出 / 从设备输入线(MOSI):主…...
wrk(1) command
文章目录 1.简介2.特点3.格式4.选项5.示例参考文献 1.简介 wrk 是一个现代的 HTTP 压力测试工具,利用现代多线程技术和高效的网络 I/O 处理,能够生成大量的并发请求,用以测试 HTTP 服务器的性能。 它是作为一种更现代的压力测试工具而设计的…...

【小程序 - 大智慧】Expareser 组件渲染框架
目录 问题思考课程目标Web Component类型说明定义组件属性添加 Shadow DOMTemplate and SlotExparser 框架原理自定义组件内置组件 下周计划 问题思考 首先,给大家抛出去几个问题: 前端框架 Vue React 都有自己的组件库,但是并不兼容&#…...

vue + echarts 快速入门
vue echarts 快速入门 本案例即有nodejs和vue的基础,又在vue的基础上整合了echarts Nodejs基础 1、Node简介 1.1、为什么学习Nodejs(了解) 轻量级、高性能、可伸缩web服务器前后端JavaScript同构开发简洁高效的前端工程化 1.2、Nodejs能做什么(了解) Node 打破了…...

服务器几核几G几M是什么意思?如何选择?
服务器几核几G几M是什么意思?我们建站、搭建网络平台都要用到云服务器,不管在腾讯云、阿里云还是别的云服务平台选购,都会接触到服务器配置。云服务器就是把物理服务器(俗称“母鸡”),用虚拟机技术虚拟出多…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...

简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
SciencePlots——绘制论文中的图片
文章目录 安装一、风格二、1 资源 安装 # 安装最新版 pip install githttps://github.com/garrettj403/SciencePlots.git# 安装稳定版 pip install SciencePlots一、风格 简单好用的深度学习论文绘图专用工具包–Science Plot 二、 1 资源 论文绘图神器来了:一行…...

Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...

selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...