代理模式(Proxy Pattern)——控制对象访问

来源:互联网 发布:软件团队 编辑:程序博客网 时间:2024/05/20 18:17

前言

背景:最近希望买一台最新的顶配Mac电脑
冲突:国内还没上,只有美国才有
解决方案:寻找代购进行购买
这就是我们的代理模式

概述

代理模式(Proxy Pattern)为另一个对象停工给一个替身或占位符以控制对这个对象的访问。它是一种对象结构型模式。

当无法直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,所访问的真实对象与代理对象需要实现相同的接口。根据代理模式的使用目的不同,代理模式又可以分为多种类型,例如远程代理虚拟代理保护代理缓冲代理等,它们应用于不同的场合,满足用户的不同需求。

远程代理可以作为另一个JVM上对象的本地代表(我们将代理描述成另一个对象的“代表”)。调用代理的方法,会被代理利用网络转发到远程执行,并且结果会通过网络返回给代理,再由代理将结果转给客户。dubbo一种分布式服务框架,就很好的利用了远程代理。

这里写图片描述

dubbo调用过程

一个系统用作客户端,一个系统则充当服务端。服务端要把自己的接口定义提供给客户端,客户端将接口定 义在spring中的bean。客户端可以直接使用这个bean,就好像这些接口的实现也是在自己代码里一样。
客户端和服务端启动的时候都会把自己的机器IP注册到zookeeper上。客户端会把zk上的服务端ip拉到磁盘上,并记录哪些ip提供哪些服务(服务端启动的时候暴露给zk)。然后调用的时候客户端会根据ip调用服务端的服务,这时候即使zk挂掉也没关系。

虚拟代理作为创建开销大的对象的代表。虚拟代表经常知道我们真正需要一个对象的时候才撞见它。当对象在创建前和创建中时,由虚拟代理来扮演对象的替身。对象创建后,代理就会将请求直接委托给对象。

这里写图片描述

防火墙代理(Firewall Proxy)控制网络资源的访问,保护主题免于“坏客户” 的侵害;——常用于公司防火墙系统中。

智能引用代理(Smart Reference Proxy)当主题被引用时,进行额外的动作,例如计算一个对象被引用的次数;

缓存代理(Caching Proxy)为开销大的运算结果提供暂时存储:它也允许多个客户共享结果。以减少计算或网络延迟。——常用于web服务器代理,以及内容管理与出版系统。

同步代理(Synchronization Proxy)在多线程的情况下为主题提供安全的访问。——常用于javaSpaces,为分布式内的潜在对象集合提供同步控制访问。

复杂隐藏代理(Complexity Hiding Proxy)用来隐藏一个类的复杂集合的复杂度,并进行访问控制。有时候也成为外观代理(Facade Proxy),这不难理解。复杂隐藏代理和外观模式是不一样的,因为代理控制访问,而外观模式只提供一组接口。

写入时复制代理(Copy-On-Write Proxy)用来控制对象的复制,方法是延迟对象的复制,知道客户真的需要为止。这是虚拟代理的变体。——在java 5的copyOnWirteArrayList用到。

类图

这里写图片描述

Subject(抽象主题),Proxy(代理主题),RealSubject(真实主题)

保护代理

java在java.lang.reflect包中有自己的代理支持,利用这个包你可以再运行时动态地创建一个代理类,实现一个或多个接口,并将方法的调用转发到你所指定的类。因为实际得代理类是在运行时创建的,我们称这个java技术为动态代理

利用java的动态代理我们创建了保护代理。类图如下。

这里写图片描述

设计模式的实现

背景说明

前段时间,一直想换了手里的设备,要不入手一台17版顶配Mac如何?那么问题来了,国内2w+,屌丝买不起。于是,是不是可以找找代购?可能会便宜200块?

代购(代理对象)代替我(真实对象)去买Mac(间接访问的操作)

代码实现

package Proxy;/** * <p>ClassName      Subject * <p>Description    抽象对象接口 * <p>Author         ChongLou * <p>Version * <p>Date           2017/10/29 11:26 */public interface  Subject {    public void request();}
package Proxy;/** * <p>ClassName      RealSubject * <p>Description    真实对象RealSubject * <p>Author         ChongLou * <p>Version * <p>Date           2017/10/29 11:28 */public class RealSubject implements Subject{    public void request() {        System.out.println("电脑太卡,想换一台电脑");        System.out.println("小伙子,想买就买,买一台17顶配Mac");    }}
package Proxy;/** * <p>ClassName      Proxy * <p>Description    代理对象类——代购 * <p>Author         ChongLou * <p>Version * <p>Date           2017/10/29 11:31 */public class Proxy implements Subject{    private Subject realSubject = null;    public void request() {        // 懒加载,创建真实对象实例        if (null == realSubject){            realSubject = new RealSubject();        }        realSubject.request();        // 做点额外的小动作        wrapMac();    }    private void wrapMac(){        System.out.println("赚了钱,就得多干活,给他包装好看点!!!");    }}
package Proxy;/** * <p>ClassName      Client * <p>Description    客户端调用 * <p>Author         ChongLou * <p>Version * <p>Date           2017/10/29 11:39 */public class Client {    public static void main(String[] args) {        Subject proxy = new Proxy();        proxy.request();    }}

运行结果

这里写图片描述

总结

  • 代理模式为另外一个对象提供代表,以便控制客户对对象的访问,管理访问的方式有很多种;
  • 代理在结构上类似装饰者,但是目的不同。装饰模式为对象加上行为,而代理则是控制访问;
  • java内置的代理支持,可以根据需要建立动态代理,并将所有调用分配到所选的处理器。
阅读全文
0 0
原创粉丝点击