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

享元(轻量级)模式

简介

享元模式(Flyweight Pattern)又叫作轻量级模式,是对象池的一种实现。类似线程池,线程池可以避免不停地创建和销毁多个对象,消耗性能。享元模式提供了减少对象数量从而改善应用所需的对象结构的方式。其宗旨是共享细粒度对象,将多个对同一对象的访问集中起来,不必为每个访问者都创建一个单独的对象,以此来降低内存的消耗,属于结构型设计模式。

享元(Flyweight)的核心思想很简单:如果一个对象实例一经创建就不可变,那么反复创建相同的实例就没有必要,直接向调用方返回一个共享的实例就行,这样即节省内存,又可以减少创建对象的过程,提高运行速度。

通用模板

  1. 创建抽象享元角色:享元对象抽象基类或者接口。

    
    // 享元接口
    public interface IFlyweight {void operation(String extrinsicState);
    }
    
  2. 创建具体享元角色:实现抽象角色定义的业务。

    
    // 具体的享元角色
    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);}
    }
    
  3. 创建享元工厂::负责管理享元对象池和创建享元对象。

    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);}
    }
    

模板测试

  1. 代码

    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");}
    }
    
  2. 结果

    Object address: 2133927002
    IntrinsicState: aa
    ExtrinsicState: aa
    Object address: 2133927002
    IntrinsicState: aa
    ExtrinsicState: b
    

内部状态和外部状态

享元模式的定义提出了两个要求:细粒度和共享对象。因为要求细粒度,所以不可避免地会使对象数量多且性质相近,此时我们就将这些对象的信息分为两个部分:内部状态和外部状态。
内部状态指对象共享出来的信息,存储在享元对象内部,并且不会随环境的改变而改变;外部状态指对象得以依赖的一个标记,随环境的改变而改变,不可共享。
比如,连接池中的连接对象,保存在连接对象中的用户名、密码、连接URL等信息,在创建对象的时候就设置好了,不会随环境的改变而改变,这些为内部状态。而当每个连接要被回收利用时,我们需要将它标记为可用状态,这些为外部状态。

应用场景

在生活中,享元模式非常常见,比如各中介机构的房源共享,再比如全国社保联网。 当系统中多处需要同一组信息时,可以把这些信息封装到一个对象中,然后对该对象进行缓存,这样,一个对象就可以提供给多处需要使用的地方,避免大量同一对象的多次创建,降低大量内存空间的消耗。 享元模式其实是工厂方法模式的一个改进机制,享元模式同样要求创建一个或一组对象,并且就是通过工厂方法模式生成对象的,只不过享元模式为工厂方法模式增加了缓存这一功能。主要应用场景如下。 (1)常应用于系统底层的开发,以便解决系统的性能问题。
(2)系统有大量相似对象、需要缓冲池的场景。

优点

(1)减少对象的创建,降低内存中对象的数量,降低系统的内存,提高效率。
(2)减少内存之外的其他资源占用。

缺点

(1)关注内、外部状态,关注线程安全问题。
(2)使系统、程序的逻辑复杂化。

“生搬硬套”实战

场景描述

一个典型的享元模式的应用场景是在处理大量细粒度对象时,比如在一个文字处理软件中表示文档中的字符。如果每个字符都作为一个独立的对象创建,那么对于一个包含数千字符的文档来说,将会有大量的对象被创建,这会消耗大量的内存。使用享元模式可以有效地减少内存使用,因为相同的字符可以被多个位置共享。

代码开发

根据模板我们知道抽象工厂和工厂方法模式一样也是拢共就是3步:

  1. 创建抽象享元角色(这里指的是字符享元接口)

    // 字符享元接口
    public interface ICharFlyweight {// 展示字符位置的方法void display(int position);
    }
    
  2. 创建具体享元角色(这里指的是字符对象的具体类)

    // 具体的字符享元实现
    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);}
    }
    
  3. 创建享元工厂(这里指的是创建字符对象的工厂)

    // 创建字符对象的工厂,如果字符对象已经存在,则直接使用,否则存储起来备用
    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
    

这样每当有已经出现过的字符出现,则复用对象。

总结

享元模式的本质是缓存共享对象,降低内存消耗。

相关文章:

享元(轻量级)模式

简介 享元模式&#xff08;Flyweight Pattern&#xff09;又叫作轻量级模式&#xff0c;是对象池的一种实现。类似线程池&#xff0c;线程池可以避免不停地创建和销毁多个对象&#xff0c;消耗性能。享元模式提供了减少对象数量从而改善应用所需的对象结构的方式。其宗旨是共享…...

基于php的幸运舞蹈课程工作室管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…...

NLP任务的详细原理与步骤的详细讲解

1. 文本分类 原理&#xff1a; 特征提取&#xff1a;文本分类首先将文本转化为数值特征&#xff0c;常用方法包括词袋模型、TF-IDF、Word Embeddings&#xff08;如Word2Vec、GloVe&#xff09;和BERT等预训练模型。模型训练&#xff1a;模型&#xff08;如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工具及开发平台&#xff0c;支持多种大语言模型和多模态AI模型。本文将详细介绍如何通过API调用智匠MindCraft中的大语言模型&#xff0c;帮助开发者快速上手。 注册与登录 访问智匠MindCraft官网&#xff0c;注册并登录账号。 进入开发者平台&…...

【TabBar嵌套Navigation案例-新特性页面-代码位置 Objective-C语言】

一、接下来,我们来说这个新特性页面 1.首先,看一下我们的示例程序,这里改一下,加一个叹号, command + R, 好,首先啊,这里边有一个新特性页面,当我这个程序是第一次安装、第一次运行、还有呢、就是当这个应用程序更新的时候,我应该去加载这个新特性页面, 然后呢,这…...

程序员如何提升并保持核心竞争力?——深入钻研、广泛学习与软技能的培养

一、引言  随着人工智能的不断发展&#xff0c;尤其是AIGC系列大语言模型的涌现&#xff0c;AI辅助编程工具正在日益普及&#xff0c;这对程序员的工作方式产生了深刻的影响。面对这一变革&#xff0c;程序员应如何应对&#xff1f;是专注于某个领域深耕细作&#xff0c;还是…...

Linux之Docker虚拟化部署

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

重构部队信息安全:部队涉密载体建设新策略

一、完善保密体系架构 1. 加强保密规章制度&#xff1a;制定或刷新关于机密信息管理的相关规定&#xff0c;明确机密信息的生成、复制、传输、使用、储存及销毁等核心环节的操作准则与责任分配&#xff0c;确保整个流程的标准化运作。 2. 明确个人保密义务&#xff1a;通过保密…...

使用Node.js的readline模块逐行读取并解析大文件

在Node.js环境中处理大文件是一个常见的需求&#xff0c;尤其是在处理日志文件、数据库导出、或任何形式的大规模文本数据时。由于Node.js是基于事件循环和非阻塞I/O的&#xff0c;它非常适合处理这类任务。然而&#xff0c;直接将整个文件内容加载到内存中可能会导致内存溢出&…...

浅谈软件安全开发的重要性及安全开发实践

在当今数字化时代&#xff0c;软件已成为企业运营的核心驱动力。然而&#xff0c;随着网络环境的日益复杂和黑客技术的不断演进&#xff0c;软件安全问题日益凸显&#xff0c;成为企业不可忽视的重大挑战。本文将从法律法规要求、企业核心数据资产保护、企业信誉等角度&#xf…...

在 NodeJs 里面如何获取 APK 的名称和 icon

最近想用 electron 写一个 adb 的可视化客户端&#xff0c;在展示安装的应用时遇到了如何获取 APK 的名称和 icon 的问题。下面就是一些解决问题的思路。 前提&#xff1a;在这里默认大家已经下载好 apk, 下面 localApkPath 就是你下载好的 apk 的路径。 小提示&#xff0c;示…...

基于VirtualBox和Ubuntu的虚拟环境搭建

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

【PHP源码】匿名来信系统H5版本V1.0免费开源

你的匿名来信H5一封你的来信源码/表白祝福短信程序/往来信/传话短信源码支持邮件发信与手机短信发信“你的匿名来信”是最近某音上爆火的一个活动话题&#xff0c;可以通过H5网站&#xff0c;编辑自己想要对某人说的话或者祝福&#xff0c;网站会把您想说的发给您预留的号码&am…...

Prompt技巧总结和示例分享

"Prompt"&#xff08;提示&#xff09;在人工智能中通常指的是输入给模型的文本&#xff0c;用于引导模型生成预期的输出。在使用人工智能助手时&#xff0c;有效的提示技巧可以帮助你获得更准确和有用的回答。 以下是一些单轮对话提示时的技巧&#xff1a; 明确具体…...

大厂校招:海能达嵌入式面试题及参考答案

SPI 协议的一些基础知识 SPI(Serial Peripheral Interface)即串行外设接口,是一种高速的、全双工、同步的通信总线。 SPI 主要由四根信号线组成: 时钟线(SCLK):由主设备产生,用于同步数据传输。时钟的频率决定了数据传输的速度。主设备输出 / 从设备输入线(MOSI):主…...

wrk(1) command

文章目录 1.简介2.特点3.格式4.选项5.示例参考文献 1.简介 wrk 是一个现代的 HTTP 压力测试工具&#xff0c;利用现代多线程技术和高效的网络 I/O 处理&#xff0c;能够生成大量的并发请求&#xff0c;用以测试 HTTP 服务器的性能。 它是作为一种更现代的压力测试工具而设计的…...

【小程序 - 大智慧】Expareser 组件渲染框架

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

vue + echarts 快速入门

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

服务器几核几G几M是什么意思?如何选择?

服务器几核几G几M是什么意思&#xff1f;我们建站、搭建网络平台都要用到云服务器&#xff0c;不管在腾讯云、阿里云还是别的云服务平台选购&#xff0c;都会接触到服务器配置。云服务器就是把物理服务器&#xff08;俗称“母鸡”&#xff09;&#xff0c;用虚拟机技术虚拟出多…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

java_网络服务相关_gateway_nacos_feign区别联系

1. spring-cloud-starter-gateway 作用&#xff1a;作为微服务架构的网关&#xff0c;统一入口&#xff0c;处理所有外部请求。 核心能力&#xff1a; 路由转发&#xff08;基于路径、服务名等&#xff09;过滤器&#xff08;鉴权、限流、日志、Header 处理&#xff09;支持负…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

【Oracle APEX开发小技巧12】

有如下需求&#xff1a; 有一个问题反馈页面&#xff0c;要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据&#xff0c;方便管理员及时处理反馈。 我的方法&#xff1a;直接将逻辑写在SQL中&#xff0c;这样可以直接在页面展示 完整代码&#xff1a; SELECTSF.FE…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡&#xff08;如 HAProxy、AWS NLB、阿里 SLB&#xff09;发起上游连接时&#xff0c;将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后&#xff0c;ngx_stream_realip_module 从中提取原始信息…...

python如何将word的doc另存为docx

将 DOCX 文件另存为 DOCX 格式&#xff08;Python 实现&#xff09; 在 Python 中&#xff0c;你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是&#xff0c;.doc 是旧的 Word 格式&#xff0c;而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

什么是Ansible Jinja2

理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具&#xff0c;可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板&#xff0c;允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板&#xff0c;并通…...