设计模式——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 一样。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

成熟的内外网数据交换方案,如何实现跨网传输?

网络迅速发展,我们可以从网络上查找到各式各样的信息,但是同时网络安全问题也随之严重。近几年,各种有关网络安全的新闻不断被报道,数据泄露给很多企业带来了严重打击,不仅是经济损失,严重者还会对企业的声…

二进制计算

二进制的引入 十进制规则:满10进1,由数字0到9组成。 而所谓十六进制,八进制,二进制的规则也是类似。 这里为了区分十六进制和八进制,十六进制前面会加上0x,八进制前面会加个0作为区分 而二进制的规则类似于十进制&…

【时间序列篇】基于LSTM的序列分类-Pytorch实现 part2 自有数据集构建

系列文章目录 【时间序列篇】基于LSTM的序列分类-Pytorch实现 part1 案例复现 【时间序列篇】基于LSTM的序列分类-Pytorch实现 part2 自有数据集构建 【时间序列篇】基于LSTM的序列分类-Pytorch实现 part3 化为己用 在一个人体姿态估计的任务中,需要用深度学习模型…

uniapp css样式穿透

目录 前言css样式穿透方法不加css样式穿透的代码加css样式穿透的代码不加css样式穿透的代码 与 加css样式穿透的代码 的差别参考 前言 略 css样式穿透方法 使用 /deep/ 进行css样式穿透 不加css样式穿透的代码 <style>div {background-color: #ddd;} </style>…

Go 虚拟环境管理工具 gvm 原理介绍与使用指南

本文谈下我对 Go 版本管理的一些想法。让后&#xff0c;我将介绍一个小工具&#xff0c;gvm。这个话题说起来也很简单&#xff0c;但如果想用的爽&#xff0c;还是要稍微梳理下。 背景介绍 Go 的版本管理&#xff0c;并非包的依赖管理&#xff0c;而且关于如何在不同的 Go 版…

一文读懂:D3.js的前世今生,以及与echarts的对比

D3.js&#xff08;Data-Driven Documents&#xff09;是一种用于创建动态、交互式数据可视化的JavaScript库。它通过使用HTML、CSS和SVG等Web标准&#xff0c;将数据与文档结合&#xff0c;使得数据可以以一种直观和易于理解的方式进行呈现。D3.js的重要性在于它赋予了开发者更…

vue3 中组合键 command+Enter / shift+Enter / alt + Enter 实现换行,详细实现

vue3 中组合键实现换行 需求背景 有一个聊天室功能&#xff0c;采用输入框的形式&#xff0c;输入完毕使用Enter&#xff0c;可以直接进行发送。使用一些组合键 比如 commandEnter / shiftEnter / alt Enter … 可以实现换行操作。但现实的情况是&#xff0c;原生 Enter 天然…

动静态库的理解、制作、使用。

一.动静态库的理解。 1.什么是库&#xff1f; 代码是无穷无尽的&#xff0c;当程序猿在写一些项目时&#xff0c;未必所有代码亲历亲为&#xff0c;他们可以在网上寻找大佬写过的一些有关需求的代码&#xff0c;这些代码可以让他们拿过来直接使用&#xff0c;而省去了许多精力…

【Vulnhub通关】Kioptrix:Level 1 (#1)

文章目录 准备工作靶机基本信息下载 渗透流程主机发现目标扫描服务探测HTTP(S)服务SMB文件共享服务 权限提升本次靶机测试到此结束 注意&#xff1a;本文转载自本人稀土掘金博客。博客地址&#xff1a;御坂19008号 的个人主页 - 动态 - 掘金 准备工作 靶机基本信息 靶机名称&a…

ubuntu20安装网络调试助手遇到缺少qt4相关库的问题

最近需要做套接字通讯的工作&#xff0c;最好是有一个网络调试软件能够接受或者发送套接字&#xff0c;测试代码能够正常通讯。windows下有很多&#xff0c;但是linux下比较少&#xff0c;使用广泛的是下面这一款。 1、安装 首先从网盘&#xff08;链接: https://pan.baidu.c…

【JSON2WEB】02 JSON2WEB初步UI设计

JSON2WEB的UI初步设计&#xff0c;包括草图、登录、主页、导航树JSON2TREEE组件、表格JSON2GRID组件、表单JSON2FORM组件等。 1草图 表单作为抽屉从右边拉出。LOGO行和导航树为固定区域&#xff0c;导航树可以折叠。 2 登录页 找回账号&#xff1a;可以给邮箱&#xff08;找…

宝塔+nextcloud+docker+Onlyoffice 全开启https

折腾了我三天的经验分享 1.宝塔创建网站 nextcloud版本为28.0.1 php8.2 &#xff0c;导入nextcloud绑定域名对应的证书 &#xff0c;不用创建mysql 因为nextcloud 要求是mariadb:10.7 宝塔里没有&#xff0c;就用docker安装一个 端口设置为3307 将数据库文件映射出来/ww…

安卓开发之自动缩放布局

AutoScalingLayout 适用于 Android 的自动缩放布局。 替换布局&#xff1a; 我们只需要替换根布局所需的自动缩放&#xff0c;子布局也将实现自动缩放。 原始布局AutoScalingLayout相对布局ASRelativeLayout线性布局ASLinearLayoutFrameLayout&#xff08;框架布局&#xff…

Shell 虚拟机基线配置脚本示例

这是一个配置虚拟机基线的示例&#xff0c;包含关闭防火墙、禁用SElinux、设置时区、安装基础软件等。 这只是一个简单的模板&#xff0c;基线配置方面有很多&#xff0c;后续可以按照这个模板去逐步添加 代码示例 [rootbogon ~]# cat bastic.sh #!/bin/bashRED\E[1;31m GRE…

低功耗DC-DC电源模块的精细化PCB设计

在电子设备中&#xff0c;电源模块是核心组件&#xff0c;将输入直流电压转为设备所需的各种直流电压。DC-DC电源转换器&#xff0c;特别是基于开关方式的转换器&#xff0c;因其高效、小体积和轻重量等优点被广泛应用。但设计优秀的DC-DC电源转换器并不容易。布局、电磁兼容性…

web安全学习笔记【06】——http\https抓包

思维导图放最后 #知识点&#xff1a; 1、Web常规-系统&中间件&数据库&源码等 2、Web其他-前后端&软件&Docker&分配站等 3、Web拓展-CDN&WAF&OSS&反向&负载均衡等 ----------------------------------- 1、APP架构-封装&原生态&…

k8s-基础知识(Service,NodePort,CusterIP,NameSpace,资源限制)

Node Node 是 Pod 真正运行的主机&#xff0c;可以是物理机&#xff0c;也可以是虚拟机。 Annotations 原文链接 Annotations 是 key/value 形式附加于对象的注解。不同于 Labels 用于标志和选择对象&#xff0c;Annotations 则是用来记录一些附加信息&#xff0c;用来辅助应…

windows .vscode的json文件配置 CMake 构建项目 调试窗口中文设置等

一、CMake 和 mingw64的安装和环境配置 二、tasks.json和launch.json文件配置 tasks.json {"version": "2.0.0","options": {"cwd": "${workspaceFolder}/build"},"tasks": [{"type": "shell&q…

Intel NUC x15电池独立显卡功耗异常解决办法

买了Intel NUC x15&#xff0c;所有驱动都是安装的官方的驱动&#xff0c;但是电池续航一直尿崩。经过查找资料&#xff0c;发现是独立显卡功耗异常导致&#xff0c;也有用户给出了解决办法&#xff0c;参考NUC X15 显卡待机功耗异常解决方案 - 哔哩哔哩 (bilibili.com)。https…

洗地机哪个品牌最好用?智能洗地机推荐

在当前社会对清洁和卫生越来越重视的背景下&#xff0c;家用洗地机已经成为许多家庭不可或缺的清洁工具之一。这不仅因为它在功能上非常丰富&#xff0c;而且在使用体验上也极为强大。洗地机的自清洁功能使得清洁过程中无需亲手脏手&#xff0c;而且一些机型还支持消毒杀菌&…