设计模式:代理(Proxy)模式
设计模式:代理(Proxy)模式
一、前言
代理模式或许我们都听说过,至少知道代理(Proxy)这个东西的,否则看这篇博客也没任何意义的。什么叫做代理,代理是代替服务器去接受请求者的请求的中间人。我们也听说过代理服务器这个东西,它的作用就是帮助客户端去请求客户端想要的资源,为什么要通过这个代理呢,那是因为客户端直接去访问服务器会被拒绝(防火墙屏蔽),而代理服务器则可以直接访问服务器的,因此客户端通过代理服务器,将请求的内容交给代理服务器,代理服务器对这些内容进行重组换成自己的标识(IP),并且将请求的结果返回给用户,这样做的弊端就是访问的速度大打折扣,但是有总比没有强。那么我们的代理模式也是这个样子的,如果代理能够处理的东西(比如用户已经访问过的,服务器返回过来的没有过期的缓存),不用请求服务器了,直接返回给用户,而只有代理服务器不能处理的东西才会再次交给服务器(本人)去处理,当然这只是代理的一种策略就是为了能够加快访问速度,这样代理服务器就代替我们去访问服务器了。
代理代理,到底是代替谁去处理,大家可能有疑虑,因为用户有请求,代理服务器代替用户去请求和处理,这样说是代替用户的;可是代理有了自己的权限(缓存)之后看起来又像是代替服务器去处理一样,只有自己做不到的时候才会去麻烦这个被代理人(服务器),并且返回用户想要的数据,那么到底是代替谁去处理呢?!
让我们想一下日常生活,我们去找一个人办一件事,但是这个人可能身份很高,我们不能直接去见面,但是这样的人身边都是有代理(助理)的,因此我们找到了这个助理,告诉自己的问题,如果这个人说,这么简单的问题呀,还用麻烦我们的老板?!于是直接告诉了我答案和解决办法。那么我(客户)就美滋滋的走了,如果助理觉得问题很大,自己一个人不能解决,就会去向老板(服务器)请示,最终得到结果并且告诉我(客户端),这样来说代理一直是为老板(服务器)代理的,而客户有事情的话去找助理,助理不管自己处理还是向老板请示都是一种应该做的事情,不能说代理是为我们(客户)代理的,应该说代理是替老板代理的,因此代理代理,是替服务器代理,而不是替客户端代理,当然相信大家也听说过反向代理,这个东西就是自己组建了服务器集群,然后使用反向代理机制加快别人访问自己服务器的速度,这样自己的集群就是被代理(老板)的了。我想这应该是一个误区,大多数人可能都搞不清的地方。
二、代码
本人去处理所有事情是非常麻烦的,特别是初始化的时候都非常的耗时,因此使用代理,不到必须自己出马的时候一直按兵不动,让代理去完成这些工作,这就是代理模式。
Printable接口:代理的同源性:
package zyr.dp.proxy; public interface Printable { public abstract void setPrinterName(String name);
public abstract String getPrinterName();
public abstract void print(String word); }
Printer类:本人(相当于真正的服务器)
package zyr.dp.proxy; public class Printer implements Printable { String name;
public Printer(String name) {
this.name=name;
heavyWork();
System.out.println("生成打印机实例成功...");
} //做一点重活
private void heavyWork() {
System.out.println("本人:"+name);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void setPrinterName(String name) {
this.name=name;
}
public String getPrinterName() {
return name;
} public void print(String word) {
System.out.println("打印机"+name+"正在打印...");
System.out.println(word);
System.out.println("打印完成!");
} }
ProxyPrinter代理类:
package zyr.dp.proxy; public class ProxyPrinter implements Printable { String name;
Printer printer=null; //代理能做的事情自己去做
public synchronized void setPrinterName(String name) {
if(printer!=null){
printer.setPrinterName(name);
}
this.name=name;
} //代理能做的事情自己去做
public String getPrinterName() {
return name;
} //代理做不了的事情交给真正能做的(打印机)去做
public void print(String word) {
check();
printer.print(word);
} private synchronized void check() {
if(printer==null){
printer=new Printer(name);
}
} }
Main类:
package zyr.dp.proxy; public class Main { public static void main(String[] args) { Printable proxy=new ProxyPrinter();
proxy.setPrinterName("zyr");
System.out.println("此时代理的名字为:"+proxy.getPrinterName());
System.out.println("==遇到了代理处理不了的工作,通知服务器==");
proxy.print("hello,world!");
System.out.println("====================");
proxy.setPrinterName("lsx");
System.out.println("此时代理的名字为:"+proxy.getPrinterName());
proxy.print("hello,my country!");
} }
运行结果:
可以看到服务器的启动实在是太耗时了(睡眠5秒钟来表示),那么使用代理服务器可以轻松地处理一些事务(设置名字,获得名字),直到代理服务器无能为力的时候(print打印内容),代理服务器就会通知服务器(本人)让服务器去处理,从本例可以看到,代理是清楚的直到被代理的对象的,因为使用了委托机制,将Printer对象组合进来),但是Printer是不知道代理的,它只是被启动了而已,这说明了什么?!本人(Printer)可以不做任何改动,就可以增加很多的代理去启动本人,这样非常利于可扩展性,其实这里也使用了懒加载模式,可以看到只有到不得不使用的时候才生成被代理的实例,那么可不可以直接在代理模式之中使用懒加载机制呢,答案是不利于可扩展性,没有这种分而治之的思想好,另外就是启动Printer类本身就是一种开销。同时我们看到了代理和被代理人都实现了同样的接口,这样的好处是很大的,在Main中可以随意切换,同时能够定义相同的必须的接口。这种透明性是非常有益的,在很多模式之中都有着体现。
三、总结
代理模式是一种常用的模式,只在必要的时候生成实例,也分为很多种类,主要是按照使用去分类的,比如本例的虚拟代理,以及其他的远程代理,访问控制代理等,我们主要要理解代理的实现本质,代理的意义,以及实际的用处。代理模式与装饰器模式比较类似,都是持有了同类或父类的引用(委托机制),并且在函数之中调用了同类的方法来加工与同类同名的本类的相应方法,但是也有区别,代理模式是为了减轻被代理人的工作,在不得已的时候再去打扰被代理人,而装饰器模式是为了产生新的功能,装饰原有的属性。
设计模式:代理(Proxy)模式的更多相关文章
- 设计模式--代理(Proxy)模式
在公司,经常性听到采购部的人说采购某样东材料,采购不了,需要通过代理商才可以.以前Insus.NET也做有一个练习<找人办事,代理设计模式(Proxy)>http://www.cnblog ...
- Android与设计模式——代理(Proxy)模式
在阎宏博士的<JAVA与模式>一书中开头是这样描写叙述代理(Proxy)模式的: 代理模式是对象的结构模式.代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用. 代理模式 ...
- 代理(Proxy)模式简介
Proxy 模式简介 代理模式的两个应用: 打开文档时加载大图片 例如:如果有个对象是一张很大的图片,而这张图片需要花费很长时间才能显示出来,那么当这个图片包含在文档中的后面时,使用编辑器或浏览器打开 ...
- 十、设计模式之代理(Proxy)模式
什么是代理模式 代理模式是对象的结构模式,为其他对象提供一种对象以控制对这个对象的访问. 代理模式的结构图如下:(源自大话设计模式) Subject:定义了RealSubject和Proxy的公共 ...
- 漫谈设计模式(一):代理(Proxy)模式与适配器(Adapter)模式对比
1.前言 为什么要将代理模式与适配器模式放在一起来说呢?因为它们有许多的共同点,当然也有一些不同的地方.首先两者都是属于结构型模式.结构型模型是这样定义的: 结构型模式涉及到如何组合类和类以获得更大的 ...
- Head First 设计模式 —— 13. 代理 (Proxy) 模式
思考题 如何设计一个支持远程方法调用的系统?你要怎样才能让开发人员不用写太多代码?让远程调用看起来像本地调用一样,毫无瑕疵? P435 已经接触过 RPC 了,所以就很容易知道具体流程:客户端调用目标 ...
- 设计模式C++描述----13.代理(Proxy)模式
一. 举例说明 我们有时打开一个网站时会发现有这样的现象,网站上的文字都显示出来了,但是上面的图片还没显示,要等一会才能显示. 这些未打开的图片的位置上,还是会有图片框和一些等待的信息的,这就是代理模 ...
- 设计模式 之代理(Proxy)模式
为什么这里要定义代理呢?所谓代理代理,当然就是你不想做的事.找别人去做,这就是代理.所以,当你写代码的时候.你想保持类的简单性.重用性.你就能够把事件尽量都交给其他类去做.自己仅仅管做好自己的事.也就 ...
- 代理(Proxy)模式
代理模式的类图如下所示: 客户端想调用的是RealSubject,由于某种考虑或原因,只能直接访问到ProxySubject,再由ProxySubject去调用RealSubject,这就完成了一次代 ...
- 行为模式--代理Proxy模式(Java)
代理(AOP切面的雏形): 题记:顾名思义就是将某件事,某个东西的使用权进行为让授权转移.代理相当于中介(不同于中介者模式),在原本操作的类之间添加了一个桥梁.但代理不能去修改原有目标.比如:一个人要 ...
随机推荐
- 如何应用前端技术唤起app及判断用户来源及与原生交互的原理
做唤起时需要native端进行配合, h5唤起app这种需求是常见的.在移动为王的时代,h5在app导流上发挥着重要的作用. 目前我们采用的唤起方式是url scheme(iOS,Android平台都 ...
- (转)linux内存源码分析 - 内存回收(lru链表)
原文:http://www.cnblogs.com/tolimit/p/5447448.html 概述 对于整个内存回收来说,lru链表是关键中的关键,实际上整个内存回收,做的事情就是处理lru链表的 ...
- js需要清楚的内存模型
原型 原型重写 原型继承 组合方式实现继承 函数作用域链
- 【lua】LWT request请求处理
request请求处理 通过mod_lwt模块提供的处理程序来调用Lua脚本处理HTTP请求.具体流程: 判断该请求是否由LWT处理,如果不是,拒绝处理请求; 判断Lua脚本文件是否存在,如果不存在, ...
- c#各个版本的特性
现在unity2018.2已经支持c#7.2了 版本特性: https://www.cnblogs.com/zq20/p/6323205.html
- MySql的存储引擎介绍
下面主要介绍InnoDB.MyISAM和MEMEORY三种存储引擎. InnoDB存储引擎 InnoDB遵循CNU通用公开许可(GPL)发行.InnoDB已经被一些重量级互联网公司所采用,如雅虎.Sl ...
- UOJ #218. 【UNR #1】火车管理
Description Solution 实际上添加问题就是一个线段树区间覆盖问题,打标记就好 对于弹栈操作比较难搞,实际上也就是一个历史查询,我们不需要保存栈中的每一个元素,我们通过查找历史状态就可 ...
- golang学习之select用法
早期的select函数是用来监控一系列的文件句柄,一旦其中一个文件句柄发生IO操作,该select调用就会被返回.golang在语言级别直接支持select,用于处理异步IO问题. select用法同 ...
- shodan在渗透测试中的应用
场景1:想搜索美国所有的elasticsearch服务器 ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.设计 ...
- orderby与groupby同时使用
两个同时使用:要求排序其他字段 select c1,max(c2) as a from table group by c1 order by a; in查询按照排序结果: ,,,....)