Android设计模式--享元模式
水不激不跃,人不激不奋
一,定义
使用共享对象可有效地支持大量的细粒度的对象
享元模式是对象池的一种实现,用来尽可能减少内存使用量,它适合用于可能存在大量重复对象的场景,来缓存可共享的对象,达到对象共享,避免创建过多对象的效果,这样一来就可以提升性能,避免内存溢出等。
在享元模式中会建立一个对象容器,在经典的享元模式中该容器为一个Map,它的键是享元对象的内部状态,它的值就是享元对象本身。客户端程序通过这个内部状态从享元工厂中获取享元对象,如果有缓存,则使用缓存对象,否则创建一个享元对象并且存入容器中,这样一来就避免了创建过多对象的问题。
二,使用场景
1,系统中存在大量的相似对象
2,细粒度的对象都具备较接近的外部状态,而且内部状态与环境无关,就是说对象没有特定身份
3,需要缓冲池的场景
三,角色介绍
Flyweight:享元对象抽象基类或接口
ConcreteFlyweight:具体的享元对象
FlyweightFactory:享元工厂,负责管理享元对象池和创建享元对象
四,使用案例
假设在吃鸡游戏中,每局游戏都会有100个玩家参与游戏,所以每局游戏都会创建100个玩家角色,如果一个玩家进行了10局游戏,他的角色就会被创建10次。这样就会造成频繁的GC,从而影响性能。如果我们使用享元模式,将玩家的姓名作为key,玩家角色作为value存放在内存中,这样就不会频繁的去创建玩家角色,避免造成不必要的资源浪费。
首先,创建一个玩家角色接口作为享元对象抽象接口,该接口定义玩家自己选择皮肤玩游戏:
public interface Player {/*** 玩游戏* @param skin 自己选择的皮肤* */void playGame(String skin);
}
然后创建具体的享元对象 :
public class ConcretePlayer implements Player{private String name;public ConcretePlayer(String name) {this.name = name;}@Overridepublic void playGame(String skin) {System.out.println("玩家"+name+"使用"+skin+"角色玩游戏");}
}
最后创建享元工厂:
public class PlayerFactory {private static HashMap<String,Player> map =new HashMap<>();public static Player createPlayer(String name){if(map.get(name)==null){System.out.println("创建新的角色");ConcretePlayer concretePlayer =new ConcretePlayer(name);map.put(name,concretePlayer);return concretePlayer;}else {System.out.println("从缓存中拿取角色");ConcretePlayer player = (ConcretePlayer) map.get(name);return player;}}
}
使用:
Player player = PlayerFactory.createPlayer("N港之王");
player.playGame("红螳螂");
Player player1 = PlayerFactory.createPlayer("N港之王");
player1.playGame("黄螳螂");
Player player2 = PlayerFactory.createPlayer("N港之王");
player2.playGame("紫螳螂");
输出:
这样,即使玩家使用同一角色玩了好多把游戏,都只创建了一次角色,其余的都是从缓存中获取的
五,总结
享元模式实现比较简单,但是它的作用在某些场景确实及其重要。它可以大大减少应用程序创建的对象,降低程序内存的占用,增强程序的性能,但它同时也提高了系统的复杂性,需要分离出外部状态和内部状态,而且外部状态具有固化特性,不应该随内部状态改变而改变,否则导致系统的逻辑混乱。
享元模式的优点在于它大幅度地降低内存中对象的数量,但是,它做到这一点所付出的代价也是很高的。
享元模式使得系统更加复杂。为了使对象可以共享,需要将一些状态外部化,这使得程序的逻辑复杂化。
享元模式将享元对象的状态外部化,而读取外部状态使得运行时间稍微变长。
参考文献:Android源码设计模式解析与实战
相关文章:

Android设计模式--享元模式
水不激不跃,人不激不奋 一,定义 使用共享对象可有效地支持大量的细粒度的对象 享元模式是对象池的一种实现,用来尽可能减少内存使用量,它适合用于可能存在大量重复对象的场景,来缓存可共享的对象,达到对象…...
人工智能对我们的生活影响有多大
人工智能给我们的生活带来了巨大的影响!它像魔术师一样,帮我们解决问题、提供建议,甚至预测未来。从智能手机到智能家居,人工智能让我们的生活变得更便捷、更智能。它是我们生活中的得力助手,让我们感受到科技的魅力&a…...

【蓝桥杯选拔赛真题26】C++字符串逆序 第十三届蓝桥杯青少年创意编程大赛C++编程选拔赛真题解析
目录 C/C++字符串逆序 一、题目要求 1、编程实现 2、输入输出 二、算法分析...

antd vue a-select 下拉框位置偏移
问题 下拉框未固定 原因 select下拉框的定位是根据body定位 解决方法 在select 标签中添加: :getPopupContainer"(triggerNode) > (triggerNode.parentElement)" :getPopupContainer"(triggerNode) > (triggerNode.parentElement)"…...

Windows10免安装PostgreSQL
1. PostgreSQL简介2. 下载3. 安装环境4. 安装 4.1. 初始化数据库4.2. 启动数据库4.3. 注册服务4.3. 卸载服务 1. PostgreSQL简介 PostgreSQL 是一种特性非常齐全的自由软件的对象-关系型数据库管理系统,是以加州大学计算机系开发的 POSTGRES 4.2版本为基础的对象关…...
lua_next
lua_pushnil(L);while(lua_next(L, -2)){// 栈状态:key : -2 value : -1// do something lua_pop(L, 1);} lua_next 先弹出一个值, 再放一对pair 到栈上, 参数 index 是表的位置 调用后: -1:value -2:key 因为会先…...
svn服务端安装
1.下载svn 2.创建一个文件夹 /usr/svn/dev 3.svnadmin create /usr/svn/dev 4.修改/usr/svn/dev/config下的目录的配置文件 authz:权限配置文件,控制读写权限passwd:账号密码配置文件svnserve.conf:svn服务器配置文件 修改svnse…...

基于C#实现十字链表
上一篇我们看了矩阵的顺序存储,这篇我们再看看一种链式存储方法“十字链表”,当然目的都是一样,压缩空间。 一、概念 既然要用链表节点来模拟矩阵中的非零元素,肯定需要如下 5 个元素(row,col,val,down,right),其中&…...

【MySQL】常用内置函数:数值函数 / 字符串函数 / 日期函数 / 其他函数
文章目录 数值函数round():四舍五入ceiling():上限函数floor():地板函数abs():计算绝对值rand():生成0-1的随机浮点数 字符串函数length():获取字符串中的字符数upper() / lower():将字符串转化…...

Python内置函数与标准库函数的详细解读
一、内置函数与标准库函数的区分 Python 解释器自带的函数叫做内置函数,这些函数可以直接使用,不需要导入某个模块。 Python 解释器也是一个程序,它给用户提供了一些常用功能,并给它们起了独一无二的名字,这些常用功能…...
计算机应用基础_错题集_Internet应用1---网络教育统考工作笔记004
5、下面关于搜索引擎的说法,不正确的是____。 A.搜索引擎既是用于检索的软件,又是提供查询﹑检索的网站 B.搜索引擎按其工作方式分为两类:全文搜索引擎和基于关键词的搜索引擎 C.现在很多搜索引擎提供网页快照的功能,当这个网页被删除或链接失效时,用户仍可使用网页快照…...

STM32之定时器--超声波测距
1、模块介绍 型号:HC-SR04 超声波测距模块是用来测量距离的一种产品,通过发送和收超声波,利用时间差和声音传播速度, 计算出模块到前方障碍物的距离。 2、超声波模块的使用方法 怎么让它发送波 Trig ,给Trig端口至…...

微信小程序 老年人心血管健康知识科普系统
本系统的功能有管理员:个人中心,用户管理,热点信息管理,疾病管理,疾病类型管理,治疗管理,治疗类型管理,护理管理,护理类型管理,科普管理,科普类型…...
influxdb2.x安装配置指南
influxdb的教程已经是很清楚了,但没有中文版翻译,以下是个人安装配置总结 如果机器上只需要一个influxdb实例,或docker安装,直接yum install 就可以了,或者采用离线安装: sudo yum localinstall influxdb…...
android APP使用指定网络上网的原理
【精选】Android app 指定网络发送数据包的实现与原理分析_bindprocesstonetwork-CSDN博客 补充: frameworks/base/core/java/android/net/ConnectivityManager.java 函数: bindProcessToNetwork 调用到了 NetworkUtils.bindProcessToNetwork 但是N…...

git-2
1.分离头指针情况下的注意事项 分离头指针指的是变更没有基于某个branch去做,所以当进行分支切换的时候,在分离头指针上产生的commit,很可能会被git当作垃圾清理掉,如果你认为是重要的内容,切记需要绑定分支 2.进一步…...

Vue实现可拖拽边界布局
Vue实现可拖拽边界布局 在前端开发中,有时需要实现一种可拖拽边界的布局,通过拖动分隔线来调整不同区域大小。例如,下图是一个典型的可拖拽边界布局,它由左右两个区域组成,左边是一个树形菜单,右边是一个上…...

Day41力扣打卡
打卡记录 第 N 位数字(找规律) 链接 class Solution:def findNthDigit(self, n: int) -> int:count, digit, start 9, 1, 1while n > count:n - countdigit 1start * 10count start * 9 * digitnum start (n - 1) // digitreturn int(str(n…...

SpringBoot项目发送邮件
📑前言 本文主要是【SpringBoot】——SpringBoot项目发送邮件的文章,如果有什么需要改进的地方还请大佬指出⛺️ 🎬作者简介:大家好,我是听风与他🥇 ☁️博客首页:CSDN主页听风与他 dz…...

Mac单独修改应用语言
方法1: 方法2: defaults write com.microsoft.Excel AppleLanguages ("zh-cn") defaults write com.microsoft.Word AppleLanguages ("zh-cn")参考:https://www.zhihu.com/question/24976020...

19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验
一、多模态商品数据接口的技术架构 (一)多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如,当用户上传一张“蓝色连衣裙”的图片时,接口可自动提取图像中的颜色(RGB值&…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...

招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...

力扣热题100 k个一组反转链表题解
题目: 代码: func reverseKGroup(head *ListNode, k int) *ListNode {cur : headfor i : 0; i < k; i {if cur nil {return head}cur cur.Next}newHead : reverse(head, cur)head.Next reverseKGroup(cur, k)return newHead }func reverse(start, end *ListNode) *ListN…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
uniapp 字符包含的相关方法
在uniapp中,如果你想检查一个字符串是否包含另一个子字符串,你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的,但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...

打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
一、方案背景 在现代生产与生活场景中,如工厂高危作业区、医院手术室、公共场景等,人员违规打手机的行为潜藏着巨大风险。传统依靠人工巡查的监管方式,存在效率低、覆盖面不足、判断主观性强等问题,难以满足对人员打手机行为精…...