设计模式:代理(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切面的雏形): 题记:顾名思义就是将某件事,某个东西的使用权进行为让授权转移.代理相当于中介(不同于中介者模式),在原本操作的类之间添加了一个桥梁.但代理不能去修改原有目标.比如:一个人要 ...
随机推荐
- 利用URL Scheme打开APP并传递数据
https://blog.csdn.net/u013517637/article/details/55251421 利用外部链接打开APP并传递一些附带信息是现在很多APP都有的功能,我在这把这部分的 ...
- c++ 网络编程(五) LINUX下 socket编程 多种I/O函数 -以及readv和writev函数用法
原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/9614056.html 一.多种I/O函数 前言:之前我们讲的数据传输一般Linux上用writ ...
- java ee的map
- Visual Studio中修改项目的输出目录
1. 如在Solution中的项目名称为 ProjectA 但在本地目录显示却想换成: MyProject 2. 应该做的修改是: 2.1. 将本地目录的 ProjectA手动修改成 MyProjec ...
- bzoj 4942: [Noi2017]整数
Description Solution 加法减法可以分开考虑,如果只有加法的话,直接暴力进位复杂度是对的 询问的时候就是把两个二进制数做差,判断第 \(k\) 位的取值 实际上我们只需要判断 \(1 ...
- bitbucket 源代码托管
5个人以下可以免费使用,不限制仓库的数量; 国外的注册需要开启蓝灯FQ; 1.注册账号 maanshancss w1-g1@qq.com;创建仓库; 然后拷贝现有项目 然后提交 然后push; 2.写 ...
- js生成6位随机码
js生成6位随机数字: let chars = '0123456789'; /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/ let maxPos = chars.len ...
- jsp、servlet笔记
1.init 初始化Jsp&Servlet方法 destroy 销毁Jsp&Servlet之前的方法 service 对用户请求生成响应的方法2.Jsp文件必须在jsp服 ...
- 三年从前端小工到架构-知乎 Live 学习整理
最近在知乎上学习了vczero (王利华,簋谣)的知乎Live「三年从前端小工到架构」,感觉受益匪浅,现将本次Live学习笔记记录如下. 本次 Live 主要包括以下内容 • 0-3 年的前端工程 ...
- 关于async和await的一些误区
微软的MSDN说async和await是“异步”,但是不少人(包括笔者自己)有一些误区需要澄清:为什么await语句之后没有执行?不是异步吗? [示例代码] public partial class ...