做的网站没流量吗,地产网站设计,北京网站建设外包公司排名,怎样进行网站推广诗有可解不可解#xff0c;若镜花水月勿泥其迹可也 —— 谢榛 文章目录 定义图纸一个例子#xff1a;图片搜索器图片加载搜索器直接在Image添加组合他们 各种各样的代理远程代理#xff1a;镜中月#xff0c;水中花保护代理#xff1a;对象也该有隐私引用代理#xff1a;… 诗有可解不可解若镜花水月勿泥其迹可也 —— 谢榛 文章目录 定义图纸一个例子图片搜索器图片加载搜索器直接在Image添加组合他们 各种各样的代理远程代理镜中月水中花保护代理对象也该有隐私引用代理我什么时候可以动手虚拟代理我们真的需要全部信息吗 定义
为其他对象提供一种代理以控制对这个对象的访问 图纸 一个例子图片搜索器
某天你突发奇想想做一个可以展示指定文件夹内所有图片的桌面应用。这个应用很简单遍历文件夹发现图片文件把图片加载到GUI上的图片列表里显示图片名和图片就像这样 图片加载
为了实现这样的效果你编写了自己的 Image 类簇并给予他一个通过 InputStream 来载入图片并获取图片信息的方法就像这样 我们可以通过 Image 中的 loadByStream 方法把参数输入流内的图片文件加载到内存中来并把获取到的信息写到 messageMap 中根据需要获取里面的内容反馈给 client
至此不出意外的话我们根据 Image对象 提供的信息绘制出GUI后就可以得到截图类似的效果 搜索器
随着文件夹里面的图片越来越多在里面找到你需要的变得越来越困难于是新的想法出现了你想要加一个搜索框用于筛选读取到的图片 这个需求很合理但是实现起来却出现了问题
Image 是通过把图片载入到内存的方式来获取图片信息的这就意味着我要获取所有图片的文件名用于搜索之前必须加载所有的图片这是无法接受的 经过我们分析只要不把文件加载到内存里只是遍历文件夹获取其中的所有文件的文件名是很快的通过File
也就是说对于一个文件来说他在程序里会同时拥有对应的 Image对象 和 File对象
我当然希望这两个对象可以绑定在一起那该怎么做呢 直接在Image添加
直接添加到Image中就像这样 看起来很美好也很必要
可是我要为将来考虑这个程序里面的 Image 不一定都从硬盘上读取文件我允许他从任何输入流中加载图片出来
这种时候file对象的存在就显得很尴尬而且会导致getName方法的异常我又得给他写 if(filenull)……
这显然是很糟糕的设计 组合他们
既然直接添加不可以那很显然就只能用另一个类来把他们组合起来
但是怎么组合有讲究
组合他们的这个类本质上还是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类 的编写者的想法去跟文件交互就像 gettersetter 一样。