设计模式十二:享元模式(Flyweight Pattern)
当我们需要创建大量相似对象时,享元模式可以帮助我们节省内存空间和提高性能。该模式通过共享相同的数据来减少对象的数量。
在享元模式中,有两种类型的对象:享元(Flyweight)和非享元(Unshared Flyweight)。享元对象是可共享的,它包含内部状态和外部状态。内部状态是不变的,它可以在多个对象之间共享。外部状态是会变化的,它由客户端代码传递给享元对象,因此它不能被共享。
享元模式的核心思想是将相同的外部状态提取出来作为共享对象,在使用时通过传递外部状态进行对象的定制。这样就可以避免创建大量相同的对象,从而减少内存占用。
享元模式的适用场景
享元模式适用于需要创建大量相似对象,并希望节省内存空间和提高性能的场景。它通过共享相同的状态来减少对象的数量,以达到优化性能的目的。
- 当一个类有大量的相似对象,且这些对象可以共享一些相同的状态时,可以考虑使用享元模式。通过共享相同的状态,可以减少对象的数量,节省内存空间。
- 当大量对象导致内存占用过高,而且这些对象的状态可以被外部化时,可以使用享元模式来共享这些外部状态。外部状态可以由客户端代码传递给享元对象,从而避免创建大量重复的对象。
- 当需要在多个对象之间共享和复用状态时,可以使用享元模式。通过共享状态,可以实现对象的复用,提高性能。
- 当对象的数量很大,但每个对象只包含少量的状态时,可以考虑使用享元模式。通过共享状态,可以减少对象的数量,降低系统的复杂性和维护成本。
- 当希望将对象的内部状态和外部状态分离,并通过外部状态对对象进行定制时,可以使用享元模式。内部状态是不变的,可以在多个对象之间共享,而外部状态会变化,可以通过客户端代码传递给享元对象。
享元模式主要包含以下几个角色:
在享元模式中,具体享元对象之间可以共享内部状态,而外部状态是可变的,由客户端代码传递。享元工厂负责管理和创建享元对象,避免重复创建相同的享元对象。客户端通过享元工厂获取享元对象,并根据需要传入外部状态,从而定制享元对象的行为。这样可以在节省内存空间的同时,实现定制化的复用。
- 享元(Flyweight):它是一个接口或抽象类,定义了具体享元对象的共享方法和获取外部状态方法。
- 具体享元(Concrete Flyweight):实现了享元接口,包含内部状态和外部状态两部分。内部状态是不变的,可以被多个享元对象共享;外部状态是可变的,需要在使用时传入。
- 享元工厂(Flyweight Factory):管理和创建享元对象,通过一个数据结构(如哈希表)存储已经创建的享元对象,并根据需要进行复用或创建新的享元对象。
- 客户端(Client):通过享元工厂来获取享元对象,并根据需要传入外部状态。客户端可以通过共享享元对象的内部状态来节省内存空间和提高性能。
享元模式具体实现
以下实例通过创建歌曲享元工厂,实现歌曲的播放
享元接口
public interface Song {void play();
}
具体享元
/*** 国风歌曲*/
public class ChineseSong implements Song {private String songName;public ChineseSong(String songName) {this.songName = songName;}@Overridepublic void play() {System.out.println("A song called" + songName + " was played");}}
享元工厂
/*** 享元工厂类*/
public class FlyweightFactory {//定义一个集合,用于共享里面的对象private static Map<String, Song> songMap = new HashMap<>();public static ChineseSong getSong(String songName) {ChineseSong chineseSong = (ChineseSong) songMap.get(songName);if (chineseSong == null) {chineseSong = new ChineseSong(songName);songMap.put(songName, chineseSong);System.out.println("Add a new ChineseSong with : " + songName);}return chineseSong;}}
客户端
/*** 享元模式* 利用享元模式实现播放歌曲*/
public class Flyweight {public static void main(String[] args) {Song 稻香 = FlyweightFactory.getSong("稻香");稻香.play();Song 花田错 = FlyweightFactory.getSong("花田错");花田错.play();Song 稻香2 = FlyweightFactory.getSong("稻香");稻香2.play();}}
运行结果
Add a new ChineseSong with : 稻香
A song called稻香 was played
Add a new ChineseSong with : 花田错
A song called花田错 was played
A song called稻香 was played
在 FlyweightFactory中,使用了一个哈希表 Map 来存储已经创建的 Song对象。在获取 Song对象时,首先检查 Map 中是否已存在该颜色的对象,如果存在则直接返回,如果不存在则创建一个新的 Song对象,并将其加入到 Map 中。
享元模式的优缺点
享元模式的优点:
- 减少内存使用:享元模式通过共享对象来减少内存使用,特别是当有大量相似对象需要创建时。通过共享对象,可以节省大量的内存空间。
- 提高性能:由于享元模式共享对象,避免了频繁地创建和销毁对象,从而提高了系统的性能。
- 简化复杂对象:享元模式可以将复杂对象拆分成多个简单的共享对象,使得对象的创建和管理更加简单。
享元模式的缺点:
- 共享对象的状态不可变:由于享元对象被多个客户端共享,因此其内部状态必须是不可变的。如果某个客户端修改了共享对象的状态,可能会影响其他客户端的操作。
- 对象共享可能增加复杂性:在实现享元模式时,需要对对象进行合理的划分和管理,这可能增加系统的复杂性。
- 不适用于所有情况:享元模式主要适用于有大量相似对象需要共享的场景。对于不需要共享对象或者对象之间差异较大的情况,使用享元模式可能并不适合。
享元模式在需要创建大量相似对象且需要节省内存的场景下具有很好的优势,但也需要注意其适用性和状态管理的复杂性。
相关文章:
设计模式十二:享元模式(Flyweight Pattern)
当我们需要创建大量相似对象时,享元模式可以帮助我们节省内存空间和提高性能。该模式通过共享相同的数据来减少对象的数量。 在享元模式中,有两种类型的对象:享元(Flyweight)和非享元(Unshared Flyweight&a…...
【LeetCode】88. 合并两个有序数组 - 双指针
这里写自定义目录标题 2023-8-7 22:35:41 88. 合并两个有序数组 双指针 2023-8-7 22:35:41 class Solution {public void merge(int[] nums1, int m, int[] nums2, int n) {int last m n ;while(n > 0){if(m > 0 && nums2[n-1] > nums1[m-1]){nums1[las…...
HarmonyOS应用开发的新机遇与挑战
HarmonyOS 4已经于2023年8月4日在HDC2023大会上正式官宣。对广大HarmonyOS开发者而言,这次一次盛大的大会。截至目前,鸿蒙生态设备已达7亿台,HarmonyOS开发者人数超过220万。鸿蒙生态充满着新机遇,也必将带来新的挑战。 HarmonyO…...
Qt中qmake、构建、运行、清理的区别
Qt 中默认的执行顺序:qmake--- 编译 --- 运行。 一、qmake qmake: 根据之前项目指南创建的项目文件 .pro,并且运行 qmake [qmake xx.pro]生成调试 [build-ttt-***-Debug] 或者发布 [build-ttt-***-Release] 目录(这个是影子构建…...
【设计模式——学习笔记】23种设计模式——观察者模式Observer(原理讲解+应用场景介绍+案例介绍+Java代码实现)
文章目录 案例引入原始方案实现实现问题分析 介绍基础介绍登场角色 案例实现案例一类图实现分析 案例二类图实现 观察者模式在JDK源码的应用总结文章说明 案例引入 有一个天气预报项目,需求如下: 气象站可以将每天测量到的温度、湿度、气压等等以公告的…...
【奇葩瑞萨-004】RX系列单片机的GPIO初始化
RX系列单片机的GPIO初始化 与IO口相关的寄存器端口(PORT)寄存器端口功能控制(MPC)寄存器MPC.PmnFPS的设置过程MPC寄存器设置注意事项 端口Pmn的初始化不同端口模式下,PORT、MCP寄存器的配置顺序 感想:与STM…...
【Git】Git切换地址
如何切换git代码地址? 1、查看当前远程 url git remote -v执行命令后,可以看见当前有2个URL。 远程 URL 在一般情况下有两个,分别是 fetch 和 push。 fetch URL 是用于从远程仓库获取最新版本的数据。当您运行 git fetch 命令时…...
elementUI点击当前行更改当前行状态(数据更新DOM不更新问题解决)
<template slot-scope"{row,$index}" slot"menu"><el-button v-if"row.editable" type"text" size"small" click"changeStatus(row,$index)">编辑</el-button><el-button v-else type"…...
python爬取阿里巴巴商品页面数据api
以下是使用Python爬取商品页面的示例代码: import requests from bs4 import BeautifulSoup# 定义要爬取的商品链接 url https://www.alibaba.com/product-detail/High-Quality-Custom-Logo-Printing-Black_60802527914.html# 发送请求 response requests.get(ur…...
angular-mat-select 多选 实现按选择顺序排序
mat-select 正常情况下,多选后,已选项是按列表顺序进行排序,如果我想实现按照点击项目的顺序进行排序,我该如何做呢? [参考网址](Angular order of selected option in multiple mat-select - Stack Overflow) sortComparator是Angular Material中mat-select组件的一个属…...
爬虫010_列表高级_添加_append_extend_修改_查询_in_not int_删除_del_pop_remove---python工作笔记029
然后再来看列表操作 首先添加append方法 然后插入,坐标是要插入的下标,右边是插入的内容 看结果 1,2,3,4,5,6 然后这个extend,是逐个插入,放到后边 然后是修改,直接对下标赋值 看结果</...
微服务服务拆分和远程调用
一、服务架构比较 单体架构:简单方便,高度耦合,扩展性差,适合小型项目。例如:学生管理系统 分布式架构:松耦合,扩展性好,但架构复杂,难度大。适合大型互联网项目&#x…...
MySQL8.1源码安装与部署
官方文档 https://downloads.mysql.com/archives/community/https://dev.mysql.com/doc/refman/8.1/en/binary-installation.html官方文档源码安装步骤 # Preconfiguration setup $> groupadd mysql $> useradd -r -g mysql -s /bin/false mysql # Beginning of source-b…...
algebraic reconstruction technique(ART)
数值线性代数的Kaczmarz方法被Gordon,Bender,Herman引入至CT重建中,称为ART方法。 A x b Axb Axb A A A为 m n m\times n mn的稀疏矩阵。 A A A的元素 a i j a_{ij} aij表示像素 j j j对射线 i i i投影的贡献。 A A A的行向量 a i T a…...
oracle11g安装
oracle11g安装 安装环境 虚拟机版本:centos7.9 虚拟机ip:192.168.5.144 oracle版本:11g oracle安装包:p13390677_112040_Linux-x86-64_1of7.zip,p13390677_112040_Linux-x86-64_2of7.zip,p13390677_11204…...
网络防御(9)
.一、SSL工作过程是什么? SSL位于应用层和传输层之间,它能够为基于TCP等可靠连接的应用层协议提供安全性保证。SSL协议本身分为两层: 上层为SSL握手协议(SSL handshake protocol)、SSLpassword变化协议(S…...
Spring核心与设计思想
文章目录 Spring是什么?认识Spring IoC容器传统的开发图书管理系统设计可能导致的问题 使用IoC容器 Spring是什么? Spring是一个用于构建企业级应用程序的开源框架,它为Java开发者提供了一种简化和加速应用程序开发的方式。Spring框架提供了…...
【stream的使用】使用stream.filter过滤List对象
Stream初相识 概括讲,可以将Stream流操作分为3种类型: 创建Stream Stream中间处理 终止Steam 每个Stream管道操作类型都包含若干API方法,先列举下各个API方法的功能介绍。 开始管道 主要负责新建一个Stream流,或者基于现有的数组…...
Flink多流处理之connect拼接流
Flink中的拼接流connect的使用其实非常简单,就是leftStream.connect(rightStream)的方式,但是有一点我们需要清楚,使用connect后并不是将两个流给串联起来了,而是将左流和右流建立一个联系,作为一个大的流,并且这个大的流可以使用相同的逻辑处理leftStream和rightStream,也可以…...
对任意类型数都可以排序的函数:qsort函数
之前我们学习过冒泡排序: int main() {int arr[] { 9,7,8,6,5,4,3,2,1,0 };int sz sizeof(arr)/sizeof(arr[0]);int i 0;for (i 0; i < sz-1; i) {int j 0;for (j 0; j < sz-1-i; j) {if (arr[j] > arr[j 1]){int temp 0;temp arr[j];arr[j] ar…...
测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
