Java设计模式(15)-代理模式
虽然马上就是2021年了,但是大家回想起去年(2020年初)的时候,是不是高兴不起来呢?人类还没有彻底战胜新冠病毒之前,我们还是要遵从国家号召:多居家、少聚集、勤洗手、戴口罩!疫情期间,我们足不出户免不了要点外卖。如果没有外卖配送服务,那么你可能得自己去餐厅取餐了。还好,我们可以享受外卖配送服务,只需要点好餐,然后外卖小哥回到餐厅取餐然后直接送到我们手上,这样我们就不需要跟餐厅直接接触了,也减少了感染的风险。其实,外卖小哥就是一个代理,他作为一个中间角色(其实就是中介),帮助用户去餐厅取餐然后送餐给用户,这样用户就不需要直接面对餐厅。 1. 什么是代理 什么是代理?代理就是中介,它提供与服务提供方相同或者相似的功能,客户不再直接面对服务提供方,而是先找代理,再由代理去与服务提供方交互完成功能。现实生活中,有很多代理的例子,比如前边提到的外卖订餐,外卖小哥就是一个代理角色;又如,购买火车票,火车票代售点就是一个代理角色,用户直接可以去代售点购买车票;再如,各种中介所,如婚姻中介所、房产中介等等,都是代理。 在软件中,代理主要指的就是本文要探讨的代理模式,或者模式中的代理类,我们 稍后 再细说。 在网络中,代理服务器(Proxy Server),专门用来代理网络用户去取得网络信息。代理服务器又有正向代理和反向代理的区分。 1.1. 正向代理和反向代理 正向代理和反向代理,其实是按照代理服务所在位置、客户端对代理服务器是否有感知来考虑的。 1、正向代理 正向代理,其服务器位于客户端,客户端需要访问目标服务器,但是不会直接访问,而是先访问代理服务器,然后再由代理服务器转发请求到目标服务器。也就是说,正向代理其代理的是客户端的请求,客户端明确知道代理服务器的地址,然后在连接到代理服务器使其转发请求到目标服务器。其原理如下: Figure 1. 正向代理示意图 如图所示,客户端链接到代理服务器(Proxy),客户端和代理服务器位于同一个网络中。 正向代理的主要用途是,客户端由于某些原因不能直接访问目标服务器,但是代理服务器可以,因此通过代理服务器作为跳板从而达到访问目标服务器的目的。例如,我们需要访问Google网站,但是国内无法访问,我们需要使用一些代理服务或软件(它们可以访问Google),这些服务和软件就是正向代理服务器。各大操作系统都有代理服务设置,例如macOS的: Figure 2. MacOS中网络代理设置 2、反向代理 反向代理,其实是相当于正向代理而言的。在反向代理中,代理服务器与目标服务器位于同一网络中,代理服务器代理并隐藏目标服务器,客户端无需知道代理服务器的存在。原理如下: Figure 3. 反向代理示意图 代理服务器就像服务端的一道防火墙,既可以过滤掉非法的请求,又可以隐藏目标服务其的真实地址等信息,对外提供统一的访问入口,提到服务端的安全性。另外,代理服务器能够实现网络负载均衡,将请求分发到不同的目标服务器上,以缓解请求压力,提高访问速度和性能。 反向代理在网络应用中使用非常普遍,常见的软件如Nginx、Apache等都可以作为反向代理服务器。 1.2. 为什么要使用代理 前边说过了正向代理和反向代理的作用,总结一下,代理有如下的作用: 访问客户端不能直接访问的服务器,比如Google、Facebook等 提高网络访问速度,例如访问某些网站速度很慢,但是代理服务器访问之很快,这样客户端通过访问代理服务器可以提高网络速度,比如常见的网络加速器 实现安全保护,比如反向代理服务器可以设置规则过滤非法请求,也可以隐藏服务器IP地址和端口以保护后端服务器,还可以做权限认证等 实施负载均衡,反向代理服务器可以按照既定策略将不同的请求分发到不同的后端服务器上,缓解其访问压力,如常见的轮询、按IP Hash、按请求URL hash、随机选择、最小访问、按地域选择等负载均衡策略 实现动静分离,反向代理服务器支持直接访问静态资源,不需要后端服务器支持,这样可以加速静态页面的访问,如Nginx对静态资源的访问支持非常好,性能强大 了解了什么是代理,接下来我们看看在计算机软件中,代理模式的概念。 2. 代理模式简介 技术来源于生活,代理模式是一种生活中代理运用的总结。DP对代理模式(Proxy Pattern)的定义如下:给对象提供一个代理以控制对该对象的访问。 当客户端不能直接依赖目标对象,又或是想要增强目标对象的功能,可以为其创建一个代理对象(中介),然后客户端访问代理对象而不直接依赖目标对象,再由中介对象来访问目标对象。这种设计模式就是代理模式,其结构如下图所示: 可以看到,代理模式有几种角色: 抽象主题角色(Subject: 抽象类或接口,用来定义业务功能的公共方法 真实主题角色(RealSubject): 实现了抽象主题(Subject)接口,完成具体业务功能实现。它就是目标对象,客户端需要依赖它提供的功能 代理对象(Proxy): RealSubject的代理实现,保证与其具有相同的功能,因此也会实现Subject接口。代理对象内部会聚合RealSubject,具体功能会调用RealSubject来完成,同时内部也可以增强RealSubject的功能 从结构上看,代理模式与 适配器模式 类似,两者都存在一个中间对象,其都会聚合具体对象并实现一个抽象接口,但是它们的目的并不相同:代理模式更强调对象的访问控制和功能增强,而适配器模式更强调功能的转换。 代理模式的主要优点: 代理模式在客户端与目标对象之间增加了中间对象,可以控制目标对象访问 代理对象可以扩展目标对象的功能 其主要缺点: 代理模式会造成系统设计中类的数量增加 在客户端和目标对象之间增加一个代理对象,中转过程会影响请求速度 增加了系统的复杂度 3. Java中代理实现的三种方式 代理可以分为静态代理和动态代理,动态代理技术有效的减少了上边的缺点。 3.1. 静态代理 静态代理,其实就是为每一个目标对象创建一个代理类,客户端调用代理类来完成业务功能。 Figure 4....