Java设计模式 —— 【结构型模式】享元模式(Flyweight Pattern) 详解

文章目录

  • 概述
  • 结构
  • 案例实现
  • 优缺点及使用场景


概述

  • 享元模式也叫蝇量模式:运用共享技术有效地支持大量细粒度的对象

  • 常用于系统底层开发,解决系统的性能问题。像数据库连接池,里面都是创建好的连接对象,在这些连接对象中有我们需要的则直接拿来用,避免重新创建,如果没有我们需要的,则创建一个;

  • 享元模式能够解决重复对象的内存浪费的问题,当系统中有大量相似对象,需要缓冲池时。不需总是创建新对象,可以从缓冲池里拿。这样可以降低系统内存,同时提高效率;

  • 享元模式经典的应用场景就是池技术了,String常量池数据库连接池缓冲池等等都是享元模式的应用,享元模式是池技术的重要实现方式。

定义:

享元模式是运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似对象的开销,从而提高系统资源的利用率。


结构

享元模式中存在以下两种状态:

  1. 内部状态 即不会随着环境的改变而改变的可共享部分;
  2. 外部状态 指随环境改变而改变的不可以共享的部分。享元模式的实现要领就是区分应用中的这两种状态,并将外部状态外部化。

享元模式的主要有以下角色:

  • 抽象享元(Flyweight)角色: 通常是一个接口或抽象类,在抽象享元类中声明了具体享元类公共的方法,这些方法可以向外界提供享元对象的内部数据(内部状态),同时也可以通过这些方法来设置外部数据(外部状态);
  • 具体享元(Concrete Flyweight)角色 : 它实现了抽象享元类,称为享元对象;在具体享元类中为内部状态提供了存储空间。通常我们可以结合单例模式来设计具体享元类,为每一个具体享元类提供唯一的享元对象;
  • 非享元(Unsharable Flyweight)角色 : 并不是所有的抽象享元类的子类都需要被共享,不能被共享的子类可设计为非共享具体享元类;当需要一个非共享具体享元类的对象时可以直接通过实例化创建;
  • 享元工厂(Flyweight Factory)角色 : 负责创建和管理享元角色。当客户对象请求一个享元对象时,享元工厂检査系统中是否存在符合要求的享元对象,如果存在则提供给客户;如果不存在的话,则创建一个新的享元对象。
    在这里插入图片描述

案例实现

下面的图片是众所周知的俄罗斯方块中的一个个方块,如果在俄罗斯方块这个游戏中,每个不同的方块都是一个实例对象,这些对象就要占用很多的内存空间,下面利用享元模式进行实现:将图形的相同形状的看做共享部分(内部状态),不同的颜色看做非共享部分(外部状态)
在这里插入图片描述
UML类图如下:
在这里插入图片描述
【抽象享元角色】:

俄罗斯方块有不同的形状,我们可以对这些形状向上抽取出AbstractBox,用来定义共性的属性和行为。

public abstract class AbstractBox {public abstract String getShape();public void display(String color) {System.out.println("方块形状:" + this.getShape() + " 颜色:" + color);}
}

【具体享元角色】:

定义不同的形状了,IBox类、LBox类、OBox类等。

public class IBox extends AbstractBox {@Overridepublic String getShape() {return "I";}
}public class LBox extends AbstractBox {@Overridepublic String getShape() {return "L";}
}public class OBox extends AbstractBox {@Overridepublic String getShape() {return "O";}
}

【享元工厂角色】:

提供了一个工厂类(BoxFactory),用来管理享元对象(也就是AbstractBox子类对象),该工厂类对象只需要一个,所以可以使用单例模式。并给工厂类提供一个获取形状的方法。

public class BoxFactory {private static Map<String, AbstractBox> map;private BoxFactory() {map = new HashMap<String, AbstractBox>();AbstractBox iBox = new IBox();AbstractBox lBox = new LBox();AbstractBox oBox = new OBox();map.put("I", iBox);map.put("L", lBox);map.put("O", oBox);}public static final BoxFactory getInstance() {return SingletonHolder.INSTANCE;}private static class SingletonHolder {private static final BoxFactory INSTANCE = new BoxFactory();}public AbstractBox getBox(String key) {return map.get(key);}
}

测试:

public class Client {public static void main(String[] args) {AbstractBox iBox = BoxFactory.getInstance().getBox("I");iBox.display("灰色");AbstractBox lBox = BoxFactory.getInstance().getBox("L");lBox.display("绿色");AbstractBox oBox1 = BoxFactory.getInstance().getBox("O");oBox1.display("灰色");AbstractBox oBox2 = BoxFactory.getInstance().getBox("O");oBox2.display("红色");System.out.println("oBox1.hashCode(): " + oBox1.hashCode());System.out.println("oBox2.hashCode(): " + oBox2.hashCode());System.out.println("两次获取到的O图形是否是同一个对象:" + (oBox1 == oBox2));}
}

在这里插入图片描述


优缺点及使用场景

1、优点

  • 极大减少内存中相似或相同对象数量,节约系统资源,提供系统性能;
  • 享元模式中的外部状态相对独立,且不影响内部状态。

2、缺点:

  • 为了使对象可以共享,需要将享元对象的部分状态外部化,分离内部状态和外部状态,使程序逻辑复杂。

3、使用场景:

  • 一个系统有大量相同或者相似的对象,造成内存的大量耗费;
  • 对象的大部分状态都可以外部化,可以将这些外部状态传入对象中;
  • 在使用享元模式时需要维护一个存储享元对象的享元池,而这需要耗费一定的系统资源,因此,应当在需要多次重复使用享元对象时才值得使用享元模式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/65525.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【maven】什么是坐标(依赖)继承与模块、web项目启动访问

目录 2. Maven 基础 2.1 坐标 2.1.0 什么是坐标&#xff08;依赖&#xff09; 2.1.1 获得坐标 2.1.2 使用坐标 2.1.3 依赖范围 2.1.4 依赖传递 2.1.5 依赖冲突&调节原则 2.1.6 依赖排除 2.1.7 使用第三方jar包 2.2 继承与模块 2.2.1 概述 2.2.2 分析 2.2.3 实…

操作系统论文导读(八):Schedulability analysis of sporadic tasks with multiple criticality specifications——具有多个

Schedulability analysis of sporadic tasks with multiple criticality specifications——具有多个关键性规范的零星任务的可调度性分析 目录 一、论文核心思想 二、基本定义 2.1 关键性指标 2.2 任务及相关参数定义 2.3 几个基础定义 三、可调度性分析 3.1 调度算法分…

【LeetCode】2506、统计相似字符串对的数目

【LeetCode】2506、统计相似字符串对的数目 文章目录 一、哈希表位运算1.1 哈希表位运算 二、多语言解法 一、哈希表位运算 1.1 哈希表位运算 每个字符串, 可用一个 int 表示. (每个字符 是 int 的一个位) 哈希表记录各 字符组合 出现的次数 步骤: 遇到一个字符串, 得到 ma…

uniapp使用ucharts组件

1.ucharts准备 有两种使用方式&#xff1a;一种是在uni的插件市场下载&#xff08;组件化开发&#xff09;。一种是手动引入ucharts包。官方都封装好组件了&#xff0c;我们不用岂不是浪费。 直接去dcloud插件市场&#xff08;DCloud 插件市场&#xff09;找&#xff0c;第一…

YOLOv11模型改进-模块-引入多尺度大核注意力Multi-scale Large Kernel Attention

MLKA 的提出源于图像超分辨率任务的挑战性&#xff0c;该任务需重建低质量图像缺失的高频信息&#xff0c;但因 LR 与 HR 图像对应关系复杂&#xff0c;寻找像素相关性困难。此前模型扩展容量的方法增加了训练负担和数据收集成本&#xff0c;而采用的注意力机制无法同时获取局部…

《战神:诸神黄昏》游戏运行时提示找不到emp.dll怎么办?emp.dll丢失如何修复?

《战神&#xff1a;诸神黄昏》游戏运行时提示找不到emp.dll怎么办&#xff1f;emp.dll丢失的修复方法 在畅游《战神&#xff1a;诸神黄昏》这款史诗级游戏的过程中&#xff0c;如果突然遭遇“找不到emp.dll”的错误提示&#xff0c;无疑会打断你的冒险之旅。作为一名深耕软件开…

RabbitMQ基础篇之快速入门

文章目录 一、目标需求二、RabbitMQ 控制台操作步骤1.创建队列2.交换机概述3.向交换机发送消息4.结果分析5.消息丢失原因 三、绑定交换机与队列四、测试消息发送五、消息查看六、结论 一、目标需求 新建队列&#xff1a;创建 hello.queue1 和 hello.queue2 两个队列。消息发送…

非数学专业小白第一次学习Mathematica心得和体会

文章目录 1.软件界面说明2.我为什么要学习Mathematica软件3.如何进行学习4.一些具体使用4.1正余弦函数4.2一个图里面两个函数4.3 3D图形的绘制4.4密度图4.5三维向量图4.6坐标轴说明4.7图像说明4.8绘图的图例4.9指定范围4.10指定绘图样式4.11极限方程求和4.12基本图4.13邻接矩阵…

C#实现图像骨架化(ZhangSuen细化算法)

原始图像: 骨架化后图像: 需要安装一个NuGet包:System.Drawing.Common 代码如下: using System.Drawing; using System.Drawing.Imaging;public class Image {public int Width { get; }public int Height { get; }private bool[,] pixels;// 构造函数,初始化图像的宽度…

【论文阅读笔记】IC-Light

SCALING IN-THE-WILD TRAINING FOR DIFFUSION-BASED ILLUMINATION HARMONIZATION AND EDITING BY IMPOSING CONSISTENT LIGHT TRANSPORT 通过施加一致的光线传输来扩展基于扩散模型的真实场景光照协调与编辑训练 前言摘要引言相关工作基于学习的基于扩散模型的外观和光照操纵光…

论文阅读 - 《Large Language Models Are Zero-Shot Time Series Forecasters》

Abstract 通过将时间序列编码为数字组成的字符串&#xff0c;我们可以将时间序列预测当做文本中下一个 token预测的框架。通过开发这种方法&#xff0c;我们发现像GPT-3和LLaMA-2这样的大语言模型在下游任务上可以有零样本时间序列外推能力上持平或者超过专门设计的时间序列训…

《机器学习》——线性回归模型

文章目录 线性回归模型简介一元线性回归模型多元线性回归模型误差项分析一元线性模型实例完整代码 多元线性模型实例完整代码 线性回归模型简介 线性回归是利用数理统计中回归分析&#xff0c;来确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法。 相关关系&…

redis cluster集群

华子目录 什么是redis集群redis cluster的体系架构什么是数据sharding&#xff1f;什么是hash tag集群中删除或新增节点&#xff0c;数据如何迁移&#xff1f;redis集群如何使用gossip通信?定义meet信息ping消息pong消息fail消息&#xff08;不是用gossip协议实现的&#xff0…

Excel批量设置行高,Excel表格设置自动换行后打印显示不全,Excel表格设置最合适的行高后打印显示不全,完美解决方案!!!

文章目录 说个问题&#xff08;很严重&#xff01;&#xff01;&#xff01;&#xff09;写个方案会Python看这里Python环境搭建不存在多行合并存在多行合并 不会Python看这里 说个问题&#xff08;很严重&#xff01;&#xff01;&#xff01;&#xff09; 平时处理Excel表格…

安全合规遇 AI 强援:深度驱动行业发展新引擎 | 倍孜网络CEO聂子尧出席ICT深度观察报告会!

12月24日&#xff0c;2025中国信通院深度观察报告会科技伦理与合规发展分论坛在北京举办。本次分论坛主题为“伦理先行&#xff0c;合规致远”&#xff0c;聚焦互联网广告合规治理、移动终端应用生态治理、短视频平台责任限度等前沿话题进行分享与探讨。工业和信息化部领导&…

教育行业 UI 设计基础篇:简洁直观的风格打造

在当今数字化时代&#xff0c;教育行业的线上平台如雨后春笋般涌现&#xff0c;而 UI 设计作为用户与教育产品交互的重要桥梁&#xff0c;其重要性不言而喻。对于教育行业而言&#xff0c;简洁直观的 UI 风格能够极大地提升用户体验&#xff0c;帮助学习者更高效地获取知识。 …

KaiOS 4.0 | DataCall and setupData implemention

相关文档 1、KaiOS 3.1 系统介绍 KaiOS 系统框架和应用结构(APP界面逻辑)文章浏览阅读842次,点赞17次,收藏5次。对于Java开发者而言,理解JS的逻辑调用是有点困难的。而KaiOS webapp开发又不同于现代的web开发,更像chrome浏览器内嵌模式。在这里梳理一下kaios平台web应用…

【星海随笔】删除ceph

cephadm shell ceph osd set noout ceph osd set norecover ceph osd set norebalance ceph osd set nobackfill ceph osd set nodown ceph osd set pause参考文献&#xff1a; https://blog.csdn.net/lyf0327/article/details/90294011 systemctl stop ceph-osd.targetyum re…

MySQL敏感数据进行加密的几种方法

使用MySQL内置的加密函数 AES_ENCRYPT和AES_DECRYPT函数 方法介绍&#xff1a; AES&#xff08;Advanced Encryption Standard&#xff09;是一种对称加密算法。在MySQL中&#xff0c;可以使用AES_ENCRYPT函数对数据进行加密&#xff0c;使用AES_DECRYPT函数进行解密。这种加密…

「Mac畅玩鸿蒙与硬件48」UI互动应用篇25 - 简易购物车功能实现

本篇教程将带你实现一个简易购物车功能。通过使用接口定义商品结构&#xff0c;我们将创建一个动态购物车&#xff0c;支持商品的添加、移除以及实时总价计算。 关键词 UI互动应用接口定义购物车功能动态计算商品管理列表操作 一、功能说明 简易购物车功能包含以下交互&#…