1。代理模式概述二、代理模式的结构与实现三、代理模式的应用实例四、远程代理五、虚拟代理六、Java动态代理七、代理模式的优缺点适用环境》Github:https://github.com/nateshao/design-demo/tree/main/JavaDesignPatterns/15-proxy1.代理模式概述相信大家都听说过代理模式,有静态代理,JDK动态代理,CglibProxy(Spring的内容)。接下来千语和大家一起来了解一下这几种代理模式的优缺点以及对应的使用场景商品采购示意图:采购商品分析:客户->采购网站->商品软件开发:客户端->代理对象->真实对象也有这样的类型定义:代理模式:为对象提供一个代理或占位符,代理对象控制对原始对象的访问。引入新的代理对象代理对象充当客户端对象和目标对象之间的中介去除客户看不到的内容和服务或添加客户需要的额外新服务代理模式的结构代理模式包括以下三种角色:Subject(抽象主题角色)Proxy(代理主题角色)RealSubject(真实主题角色)2.代理模式的结构与实现抽象主题类典型代码:publicabstractclassSubject{publicabstractvoidrequest();}真实主题类典型代码:publicclassRealSubjectextendsSubject{publicvoidrequest(){//业务方法的具体实现代码}}代理类典型代码:publicclassProxyextendsSubject{privateRealSubjectrealSubject=newRealSubject();//维护对真实主体对象的引用publicvoidpreRequest(){...}publicvoidrequest(){preRequest();realSubject.request();//调用真实主体对象的postRequest()方法;}publicvoidpostRequest(){...}}几种常见的代理模式远程代理(RemoteProxy):为位于不同地址空间的代理对象提供本地代理对象。这个不同的地址空间可以在同一主机中,也可以在另一台主机中。远程代理又叫大使(Ambassador)虚拟代理(VirtualProxy):如果需要创建一个资源消耗很多的对象,首先创建一个比较小的对象来表示它。真正的对象只会在需要的时候被创建。ProtectProxy:控制对一个对象的访问,为不同的用户提供不同的CacheProxy:为某个目标操作的结果提供临时存储空间,让多个客户端可以共享这些结果。SmartReferenceProxy:当一个对象被引用时,提供一些额外的操作,比如记录对象被调用的次数等。3.代理模式的应用实例某软件公司承接了某信息咨询公司的收费业务信息查询系统的开发任务。系统的基本要求是:用户进行业务信息查询前需要通过身份验证,只有合法用户才能使用查询系统;查询时,系统需要记录查询日志,以便按查询次数收取查询费用。软件公司的开发人员已经完成了业务信息查询模块的开发任务,现在希望以松耦合的方式在原有系统中加入身份验证和日志记录。function,客户端代码可以对原有的业务信息查询模块和新增功能后的业务信息查询模块进行任意对待,以后可能会在信息查询模块中增加一些新的功能。现采用代理模型设计实现充电业务信息查询系统。实例分析及类图:业务信息查询系统设计示意图业务信息查询系统结构图示例代码AccessValidator:身份验证类,业务类Logger:日志记录类,业务类Searcher:抽象查询类,充当抽象主题角色RealSearcher:concreteQuery类,作为真实主体角色ProxySearcher:代理查询类,作为代理主体角色Client:客户端测试类结果分析保护代理和智能引用代理在代理类ProxySearcher中,进行权限控制和引用计数实现了真正的主题类4.RemoteProxy动机客户端程序可以访问远程主机上的对象。远程主机可能具有更好的计算性能和处理速度,能够快速响应和处理客户端的请求。它可以隐藏网络的细节,使客户端不必考虑网络。客户端的存在完全可以认为被代理的远程业务对象是本地的而不是远程的,远程代理对象承担了大部分的网络通信工作,负责远程业务方法的调用结构。5.虚拟代理的动机对于一些占用系统资源较多或加载时间较长的对象,可以为这些对象提供虚拟代理。在成功创建真实对象之前,虚拟代理充当真实对象的替代者。真实对象创建后,虚拟代理将用户的请求转发给真实对象使用一个“假”的代理对象来代表真实对象,通过代理对象间接引用真实对象,可以提高系统的性能在某种程度上。由于对象本身或网络的复杂性,导致一个对象需要很长时间才能加载出来,此时可以使用加载时间相对较短的代理对象来代表真实对象(结合多线程技术).一个对象的加载会消耗系统资源,使得那些占用内存很多或者处理起来非常复杂的对象被推迟到它们使用的时候才创建,而在这之前,一个占用比较少的代理对象resources用来表示真实的对象,然后通过代理对象引用真实的对象(以时间换空间)6.Java动态代理动态代理(DynamicProxy)允许系统根据实际需要动态创建代理类runtime,这样同一个代理类可以代理多个不同的真实主题类,可以代理不同的方法。Java语言提供了对动态代理的支持,Java语言在实现动态代理时需要用到位于java.lang.reflect包中的一些类。代理类publicstaticClass>getProxyClass(ClassLoaderloader,Class...interfaces):该方法用于返回一个Class类型的代理类。参数中需要提供类加载器,指定代理的接口数组(与真实主题类的接口列表一致)publicstaticObjectnewProxyInstance(ClassLoaderloader,Class[]interfaces,InvocationHandlerh):此方法用于返回动态创建的代理类的实例。方法中第一个参数loader表示代理类的类加载器,第二个参数interfaces表示代理类实现的接口列表(与真实主题类的接口列表一致),第三个参数h表示分配的调用处理程序类InvocationHandler接口。InvocationHandler接口是代理处理器类的实现接口,它作为代理实例调用处理器的公共父类,代理类的每个实例都可以提供相关的具体调用处理器(InvocationHandler接口的子类)publicObjectinvoke(Objectproxy,Methodmethod,Object[]args):该方法用于处理对代理类实例的方法调用,并返回相应的结果。当调用代理实例中的业务方法时,会自动调用该方法。invoke()方法包含三个参数,其中第一个参数proxy表示代理类实例,第二个参数method表示需要代理的方法,第三个参数args表示代理方法的参数数组。动态代理类在运行时需要指定被代理的真实主体类的接口,客户端调用动态代理对象的方法时,调用请求时,请求会自动转发到类的invoke()方法InvocationHandler对象,invoke()方法将实现对请求的统一处理。动态代理实例》某软件公司想在公司的OA系统数据访问层DAO中增加一个方法调用日志来记录每个方法的时间和调用结果,现采用动态代理进行设计实现。示例代码AbstractUserDAO:抽象用户DAO类,抽象主题角色AbstractDocumentDAO:抽象文档DAO类,抽象主题角色UserDAO:用户DAO类,具体主题角色DocumentDAO:文档DAO类,具体主题角色DAOLogHandler:自定义请求处理器类Client:客户端测试class7.代理模式的优缺点及适用环境模式的优点是可以协调调用者和被调用者,在一定程度上降低系统的耦合度。客户端可以针对抽象主题角色进行编程,添加和替换代理类,无需修改源代码,符合开放封闭原则,系统具有更好的灵活性和可扩展性。该模式的优点——逐一分析远程代理:可以将一些消耗资源较多的对象和操作转移到性能更好的计算机上,提高系统的整体运行效率消耗资源少,可以在一定程度上节省系统的运行开销Buffer代理:为一个操作的结果提供临时数据缓存存储空间,以便这些结果在后续使用中共享,优化系统性能,缩短执行时间保护代理:可以控制对一个对象的访问,为不同的用户提供不同级别的使用权限。主题之间添加了代理对象,因此某些类型的代理模式可能会减慢请求的处理速度(例如保护代理)实现代理模式需要额外的工作,某些代理模式的实现过程更复杂(例如远程代理))模式适用环境当客户端对象需要访问远程主机中的对象时,可以使用远程代理。当需要用资源消耗少的对象来表示资源消耗多的对象,以减少系统开销,缩短运行时间时,可以使用它。虚拟代理当需要为频繁访问的操作结果提供一个临时存储空间,以供多个客户端共享和访问这些结果时,可以使用缓冲代理来控制对一个对象的访问,为不同的用户提供不同级别的支持。保护代理可用于访问权限。当需要为对象的访问(引用)提供一些额外的操作时,可以使用智能引用代理。
