设计模式——1_6 代理(Proxy)
诗有可解不可解,若镜花水月勿泥其迹可也
—— 谢榛
文章目录
- 定义
- 图纸
- 一个例子:图片搜索器
- 图片加载
- 搜索器
- 直接在Image添加
- 组合他们
- 各种各样的代理
- 远程代理:镜中月,水中花
- 保护代理:对象也该有隐私
- 引用代理:我什么时候可以动手?
- 虚拟代理:我们真的需要全部信息吗?
定义
为其他对象提供一种代理以控制对这个对象的访问
图纸
一个例子:图片搜索器
某天,你突发奇想,想做一个可以展示指定文件夹内所有图片的桌面应用。这个应用很简单,遍历文件夹,发现图片文件,把图片加载到GUI上的图片列表里,显示图片名和图片,就像这样:
图片加载
为了实现这样的效果,你编写了自己的 Image 类簇,并给予他一个通过 InputStream 来载入图片并获取图片信息的方法,就像这样:
我们可以通过 Image 中的 loadByStream 方法把参数输入流内的图片文件加载到内存中来,并把获取到的信息写到 messageMap 中,根据需要获取里面的内容反馈给 client
至此,不出意外的话我们根据 Image对象 提供的信息绘制出GUI后就可以得到截图类似的效果
搜索器
随着文件夹里面的图片越来越多,在里面找到你需要的变得越来越困难,于是新的想法出现了,你想要加一个搜索框,用于筛选读取到的图片
这个需求很合理,但是实现起来却出现了问题
Image 是通过把图片载入到内存的方式来获取图片信息的,这就意味着我要获取所有图片的文件名用于搜索之前必须加载所有的图片,这是无法接受的
经过我们分析,只要不把文件加载到内存里,只是遍历文件夹获取其中的所有文件的文件名是很快的,通过File
也就是说,对于一个文件来说,他在程序里会同时拥有对应的 Image对象 和 File对象
我当然希望这两个对象可以绑定在一起,那该怎么做呢?
直接在Image添加
直接添加到Image中,就像这样:
看起来很美好,也很必要
可是我要为将来考虑,这个程序里面的 Image 不一定都从硬盘上读取文件,我允许他从任何输入流中加载图片出来
这种时候file对象的存在就显得很尴尬,而且会导致getName方法的异常,我又得给他写 if(file==null)……
这显然是很糟糕的设计
组合他们
既然直接添加不可以,那很显然就只能用另一个类来把他们组合起来
但是怎么组合,有讲究
组合他们的这个类本质上还是Image
,我并不是为了用这个类的对象来复制/删除文件……他的任务是包含了 Image 的任务的
所以我们可以考虑这样做:
我们创建了一个 Image类 的 代理类 ImageFileProxy,这个代理类本质上还是 Image,当你调用他的 loadByStream 或者 getWidth 之类的方法时,他直接会去调用 super 对象的对应方法
而当你访问 getName 的时候,他里面藏着的 File 会处理对应的业务,他才不管你现在有没有把图片加载完。这样一来就可以实现一边加载一边查询了
不要小看这种写法,将来如果你突发奇想想在加载图片的时候增加一个加载进度条,那也只是新增Image的子类而已,对已有的代码不会有什么影响
那你会说,这种实现跟代理的图纸差别太大了,这不就是我平时用的继承吗?
你可以试着把Image的接口抽象出来,并在ImageFileProxy的构造方法中要求传入Image对象,就像这样:
是不是发现他成了一个标准的代理实现?
各种各样的代理
远程代理:镜中月,水中花
远程代理是指在不同的地址空间里提供对相同内容的局部代表
是不是觉得这个定义老复杂了,emmmm,举个例子,比如说数组的复制,就像这样:
数组A里存着 X/Y/Z 三个对象,接着我们复制数组A得到数组B。数组A和B的内存地址当然是不一样的,但B里面存的还是 X/Y/Z。操作B,其实跟操作A没什么区别,其实此时B就能算是A的一个远程代理
真正让远程代理广为人知的是网络相关的开发
比如说现在我有Java写成的 服务器和N个客户机,我希望在服务器上有个按钮,点击后可以直接获取客户机上的硬件信息。
要做成这个效果,根据不同的连接方式,实现方法各不相同。其中一种是利用 RMI
技术,让服务器直接调用客户机上运行的对象里的方法,并获取结果,这时候其实就是在服务器上建立客户机的 远程代理
是的,你没看错,我说的就是在服务器JVM上调用运行在其他JVM上的对象。这不是魔法,是真实可行的技术,同时他也是分布式的基础,也是远程代理大放异彩的舞台
保护代理:对象也该有隐私
当你需要管理N个具有相同根类对象的时候,十有八九会用到 容器,List也好,Set也好,或者数组、Map 这不重要
重要的是这些容器对象拥有对自己所存储的对象的完全掌控权,我的意思是说,client 可以随自己喜好对容器里面的内容增删改查,这完全不受控
不是所有的容器都允许随意往里添加或删除的内容的,这时候你就需要隐藏容器的某些接口
我们会再建一个类把真正的容器类封装起来,接着不提供被隐藏的接口的访问方式(或者根据不同的权限提供不同的行为)。而 client 只能和外部的 代理类
交互,至此实现对容器的保护,这就是保护代理
引用代理:我什么时候可以动手?
如果说工厂方法之类的模式提供了对一个对象的 创建行为的包装
的话,那么引用代理就是 对一个对象提供从创建到销毁全方面的包装
因为 client 只能通过代理类对象来访问被代理的对象,那么所有对被代理的对象的访问都是在代理类对象的监控之下的。只要你想,你可以知道被代理对象现在被多少个地方引用,他有没有进入某个有锁的区域,也可以决定被代理对象什么时候被初始化……
知道这些信息是有用的,打个比方:
- 知道多少个引用:可以做引用计数、可以在丢失所有引用时释放资源
- 了解状态是否被锁:可以控制别的对象不允许修改被代理对象的状态
- 决定何时初始化:是第一次被访问时初始化?还是跟代理类对象一起被初始化?
引用代理可以给你的程序提供很多很偏门的优化手段哒
虚拟代理:我们真的需要全部信息吗?
代理模式可以提供对对象的一种访问控制
这种控制可以是限制对象公开的接口(保护代理);也可以用来管理被代理对象何时释放(引用代理)
他甚至可以做到在某个内容没有被加载进来的情况下展示他的一部分,这就是虚拟代理
试想以下,当我们需要获取一个文件的名字和修改时间,有必要把整个文件都加载到内存里过一遍吗?
答案必然是否定的。要不然你打开【我的电脑】里面的目录一定要很久(因为你打开的时候需要过一遍文件夹里所有的文件)
在Java程序里,我们用 File 来表示一个文件,通过 File 对象的方法我们可以获取到和他所代表的文件有关的各种信息
那么请问,File 在获取硬盘上的文件的信息的时候,真的每次都会把整个文件加载到程序中吗?
肯定没有啊。倒不如说在你用 IO流 让这个文件流入程序之前,硬盘上的那个文件根本没有被载入
也就是说 File对象 和硬盘上的那个文件之间,也存在一种代理关系
File 为我们提供了一系列操作文件和读取文件信息的接口;但是换句话来说, File对象 也控制着我们访问文件的路径和方式,让我们一定是按照 File类 的编写者的想法去跟文件交互,就像 getter&setter 一样。
相关文章:

设计模式——1_6 代理(Proxy)
诗有可解不可解,若镜花水月勿泥其迹可也 —— 谢榛 文章目录 定义图纸一个例子:图片搜索器图片加载搜索器直接在Image添加组合他们 各种各样的代理远程代理:镜中月,水中花保护代理:对象也该有隐私引用代理:…...

性能优化(CPU优化技术)-NEON 介绍
「发表于知乎专栏《移动端算法优化》」 本节主要介绍基本 SIMD 及其他的指令流与数据流的处理方式,NEON 的基本原理、指令以及与其他平台及硬件的对比。 🎬个人简介:一个全栈工程师的升级之路! 📋个人专栏:…...

Kafka-服务端-KafkaController
Broker能够处理来自KafkaController的LeaderAndIsrRequest、StopReplicaRequest、UpdateMetadataRequest等请求。 在Kafka集群的多个Broker中,有一个Broker会被选举为Controller Leader,负责管理整个集群中所有的分区和副本的状态。 例如:当某分区的Le…...
ffmpeg使用手册
ffmpeg使用手册 文章目录 ffmpeg使用手册ffmpeg是什么指令总结1.查看ffmpeg版本2.mkv转mp43.裁剪 .mkv 视频4.不调节帧率,尽可能保证原视频质量的情况下将原始视频压缩4.1 crf4.2 preset 5.调节视频帧率6.调节帧率,尽可能保证原视频质量的情况下将原始视…...

操作系统导论-课后作业-ch15
对应异步社区资源HW-Relocation: 1. 种子1运行结果: 种子2运行结果: 种子3运行结果: 2. 需要将界限设置为930,结果如下: 3. 有人说原书翻译有误,原文如下所示: 原文翻译如…...

宝塔面板SRS音视频TRC服务器启动失败
首先,查找原因 1.先看srs服务在哪 find / -type f -name srs 2>/dev/null运行结果: /var/lib/docker/overlay2/5347867cc0ffed43f1ae24eba609637bfa3cc7cf5f8c660976d2286fa6a88d2b/diff/usr/local/srs/objs/srs /var/lib/docker/overlay2/5347867…...
04-Seata修改通信端口
基于docker环境部署下,可以翻看专栏之前的文章 配置文件 /home/server/seata/resources/application.yml 默认${server.port} 1000 1、修改服务端(TC)配置 seata:server:service-port: 7090 2、修改映射端口 在启动脚本中修改映射端口 docker run -id --nam…...

活动回顾丨云原生技术实践营上海站「云原生 AI 大数据」专场(附 PPT)
AI 势不可挡,“智算”赋能未来。2024 年 1 月 5 日,云原生技术实践营「云原生 AI &大数据」专场在上海落幕。活动聚焦容器、可观测、微服务产品技术领域,以云原生 AI 工程化落地为主要方向,希望帮助企业和开发者更快、更高效地…...

【数据结构与算法】4.自主实现单链表的增删查改
📚博客主页:爱敲代码的小杨. ✨专栏:《Java SE语法》 ❤️感谢大家点赞👍🏻收藏⭐评论✍🏻,您的三连就是我持续更新的动力❤️ 🙏小杨水平有限,欢迎各位大佬指点&…...

Linux系统常用命令行指令
Linux系统是一种常用于开源项目开发的生产环境,因其免费、开源、安全、稳定的特点被广泛应用于手机、平板电脑、路由器、电视和电子游戏机等嵌入式系统中,能够更加简便地让用户知道系统是怎样工作的。前几日我安装好了Red Hat Enterprise Linux 9.0&…...

java SSM园林绿化管理系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计
一、源码特点 java SSM园林绿化管理系统是一套完善的web设计系统(系统采用SSM框架进行设计开发,springspringMVCmybatis),对理解JSP java编程开发语言有帮助,系统具有完整的源代 码和数据库,系统主要采…...
【issue-halcon例程学习】edges_color.hdev
例程功能 演示如何使用edges_color,展示只能从彩色图像中提取某些边缘的图像,说明edges_color和edges_image输出之间的差异。 代码如下 dev_update_off () read_image (Image, olympic_stadium) get_image_size (Image, Width, Height) dev_close_wind…...

设计模式—行为型模式之备忘录模式
设计模式—行为型模式之备忘录模式 备忘录(Memento)模式:在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。该模式又叫快照模…...

CMS如何调优
业务JVM频繁Full GC如何排查 原则是先止损,再排查。 FGC的原因是对象晋升失败或者并发模式失败,原因都是老年代放不下晋升的对象了。 1.可能是大对象导致的内存泄漏。快速排查方法:观察数据库网络IO是否和FGC时间点吻合,找到对应…...

在PyCharm中安装GitHub Copilot插件,login之后报出如下错误:
Sign in failed. Reason: Request signInInitiate failed with message: connect ECONNABORTED 20.205.243.166:443, request id: 7, error code: -32603 前提: 设置网址:https://github.com/settings/copilot,已设置为允许 或者࿱…...

L1-093 猜帽子游戏(Java)
宝宝们在一起玩一个猜帽子游戏。每人头上被扣了一顶帽子,有的是黑色的,有的是黄色的。每个人可以看到别人头上的帽子,但是看不到自己的。游戏开始后,每个人可以猜自己头上的帽子是什么颜色,或者可以弃权不猜。如果没有…...
JVM篇--JVM调优高频面试题
1 说一下 JVM 调优的工具? JDK 自带了很多监控工具,都位于 JDK 的 bin 目录下,其中最常用的是jconsole 和 jvisualvm 这两款视图监控工具。 jconsole:用于对 JVM 中的内存、线程和类等进行监控; jvisualvm:…...

微软 AD 介绍 | 安全建议 | 防护
介绍: 什么是Active Directory(AD)? Active Directory 是由 微软开发的目录服务,用于存储和管理网络中的资源,如计算机、用户、组和其他网络对象。允许组织管理员轻松地管理和验证网络中的用户和计算机。 …...
React16源码: React中的reconcileChildren的源码实现
reconcileChildren 1 )概述 在更新了一个节点之后,拿到它的props.children要根据这个children里面的 ReactElement 来去创建子树的所有的 fiber 对象要根据 props.children 来生成 fiber 子树,然后判断 fiber 对象它是否是可以复用的 因为我…...
幻兽帕鲁Docker服务端搭建
幻兽帕鲁Docker服务端搭建 各种命令 https://bbs.saraba1st.com/2b/thread-2168983-1-1.html 存档恢复 这里直接看这个工程的readme就行:https://github.com/yoko-murasame/palworld-host-save-fix 其他参考:https://forum.gamer.com.tw/C.php?bsn7…...

网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...

【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...

MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...