【设计模式】Java 设计模式之代理模式(Proxy Pattern)

代理模式深入分析

一、概述

代理模式是一种为其他对象提供一种代理以控制对这个对象的访问的设计模式。在某些情况下,一个对象不适合或者不能直接访问另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。

代理模式的主要目的是:增强目标对象的功能;控制对目标对象的访问;实现目标对象与客户端的解耦。

二、模式结构

代理模式主要涉及三个角色:

  1. 抽象主题(Subject)角色:声明了真实主题和代理主题的共同接口,这样任何使用真实主题的地方都可以使用代理主题。
  2. 真实主题(RealSubject)角色:定义了代理所代表的真实对象,是我们最终要引用的对象。
  3. 代理主题(ProxySubject)角色:代理主题角色内部含有对真实主题的引用,从而可以操作真实主题对象,同时代理主题角色提供与真实主题相同的接口以便在任何时候都能代替真实主题。此外,代理主题角色还可以在执行真实主题操作前后添加一些操作。

三、实现方式

代理模式通常有两种实现方式:静态代理和动态代理。

  1. 静态代理
    静态代理是代理模式的最直接实现方式。代理类和被代理类实现相同的接口,代理类持有被代理类的实例,通过调用被代理类的方法来完成实际的功能。
// 抽象主题
public interface Subject {void request();
}// 真实主题
public class RealSubject implements Subject {@Overridepublic void request() {System.out.println("Called RealSubject request()");}
}// 代理主题
public class ProxySubject implements Subject {private RealSubject realSubject;public ProxySubject() {this.realSubject = new RealSubject();}@Overridepublic void request() {// 在调用真实主题前添加一些操作System.out.println("Before calling RealSubject request()");realSubject.request();// 在调用真实主题后添加一些操作System.out.println("After calling RealSubject request()");}
}
  1. 动态代理
    动态代理利用了Java的反射机制,在运行时动态地生成代理类。这种方式比静态代理更加灵活,不需要为每个被代理类编写一个代理类。Java标准库中的java.lang.reflect.Proxy类和java.lang.invoke.MethodHandles.Lookup类是动态代理的关键。
// 抽象主题
public interface Subject {void request();
}// 真实主题
public class RealSubject implements Subject {@Overridepublic void request() {System.out.println("Called RealSubject request()");}
}// 动态代理工厂
public class ProxyFactory {@SuppressWarnings("unchecked")public static <T> T getProxyInstance(Class<T> interfaceClass, InvocationHandler handler) {return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(),new Class<?>[]{interfaceClass},handler);}
}// 调用处理器
public class MyInvocationHandler implements InvocationHandler {private Object target;public MyInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 在调用方法前添加一些操作System.out.println("Before method " + method.getName());Object result = method.invoke(target, args);// 在调用方法后添加一些操作System.out.println("After method " + method.getName());return result;}
}// 客户端代码
public class Client {public static void main(String[] args) {RealSubject realSubject = new RealSubject();InvocationHandler handler = new MyInvocationHandler(realSubject);Subject subject = ProxyFactory.getProxyInstance(Subject.class, handler);subject.request();}
}

四、优缺点分析

优点:

  1. 职责清晰:将一部分工作交给代理对象处理,真实对象可以更加专注于其核心功能的实现。
  2. 控制访问:代理模式可以对访问真实对象进行一定的限制和控制,比如权限校验、访问日志记录等。
  3. 高扩展性:可以在不修改原有代码的基础上增加新的功能。

缺点:

  1. 性能损耗:由于代理对象的存在,每次访问真实对象都需要通过代理对象,因此会有一定的性能损耗。
  2. 代码复杂度:使用代理模式会增加代码的复杂度,特别是在使用动态代理时,需要编写额外的代理工厂类和调用处理器类。

五、常见应用场景

  1. 远程代理:为一个对象在不同的地址空间提供局部代表,这样可以将网络细节隐藏起来。
  2. 虚拟代理:根据需要创建开销很大的对象。通过它来存放实例化需要很长时间的真实对象。
  3. 保护代理:控制对原始对象的访问权限。
  4. 智能引用:当调用真实对象时,代理对象进行一些附加操作,如计算真实对象的引用次数等。

六、应用案例解读

以远程代理为例,假设我们有一个远程服务,客户端需要调用这个服务上的方法。出于性能和安全考虑,我们不希望客户端直接调用远程服务,而是通过一个代理对象来进行调用。代理对象负责处理网络通信、序列化/反序列化等细节,而客户端只需与代理对象交互即可。

// 远程服务接口
public interface RemoteService {String callRemoteMethod(String arg);
}// 远程服务实现(位于远程服务器上)
public class RemoteServiceImpl implements RemoteService {@Overridepublic String callRemoteMethod(String arg) {// 执行一些远程服务上的操作return "Result from remote service: " + arg;}
}// 远程服务代理
public class RemoteServiceProxy implements RemoteService {private String serverAddress;public RemoteServiceProxy(String serverAddress) {this.serverAddress = serverAddress;}@Overridepublic String callRemoteMethod(String arg) {// 处理网络通信,发送请求到远程服务器// 接收响应,并返回结果// 这里的实现会依赖于具体的网络通信库或框架String result = sendRequestToServer(serverAddress, arg);return result;}private String sendRequestToServer(String serverAddress, String arg) {// 简化示例,实际实现会涉及网络通信和序列化/反序列化return "Proxy result for server at " + serverAddress + ": " + arg;}
}// 客户端代码
public class Client {public static void main(String[] args) {RemoteService proxy = new RemoteServiceProxy("remote.server.address");String result = proxy.callRemoteMethod("Hello, remote service!");System.out.println(result);}
}

在这个案例中,RemoteServiceProxy作为远程服务的代理,负责处理与远程服务器的通信。客户端代码通过调用代理对象的callRemoteMethod方法,间接地调用远程服务上的方法。代理对象隐藏了网络通信的复杂性,使客户端代码更加简洁和易于管理。

总结来说,代理模式是一种强大的设计模式,它可以在不修改原有代码的基础上增强对象的功能、控制对象的访问以及实现解耦。通过合理地应用代理模式,我们可以构建出更加灵活、可扩展和易于维护的软件系统。
七、代理模式的变种

代理模式有多种变种,每一种都有其特定的用途和适用场景。

  1. 保护代理(Protection Proxy):控制对原始对象的访问权限。这种代理模式常用于实现访问控制,比如限制对某个方法的访问,或者检查用户权限等。

  2. 虚拟代理(Virtual Proxy):主要用于控制对开销大的对象的访问。当实际对象在创建或初始化时开销很大时,虚拟代理可以延迟对象的创建,直到真正需要时才创建。

  3. 智能引用代理(Smart Reference Proxy):当调用真实对象时,代理对象进行一些附加操作,比如引用计数、日志记录、事务处理等。

  4. 缓存代理(Caching Proxy):为开销大的运算结果提供暂时的存储,在下次运算时,如果输入相同则直接返回缓存的结果。

  5. 同步代理(Synchronization Proxy):为多个线程共享的资源提供安全访问。

八、与其他设计模式的关联

代理模式经常与其他设计模式结合使用,以实现更复杂的系统结构和功能。

  1. 与装饰器模式(Decorator Pattern):装饰器模式用于动态地给一个对象添加一些额外的职责。在某种意义上,代理模式也可以看作是一种特殊的装饰器模式,它主要关注于控制对对象的访问和增强对象的功能,而不是动态地添加职责。

  2. 与适配器模式(Adapter Pattern):适配器模式用于将一个类的接口转换成客户端所期望的另一种接口。在某些情况下,代理模式可以用来实现适配器模式,特别是当需要转换的接口涉及访问控制或延迟加载时。

九、最佳实践

  1. 明确代理的目的:在使用代理模式之前,首先要明确代理的目的,是为了增强功能、控制访问还是其他目的。

  2. 考虑性能开销:代理模式会增加一定的性能开销,因为每次访问原始对象都需要通过代理对象。因此,在性能敏感的场景中,需要仔细权衡是否使用代理模式。

  3. 保持接口一致性:代理对象应该尽量保持与原始对象相同的接口,这样客户端代码才能无缝地切换到代理对象。

  4. 谨慎使用动态代理:动态代理虽然提供了很大的灵活性,但也会增加代码的复杂性和维护成本。因此,在不需要动态代理的情况下,应尽量使用静态代理。

十、代理模式在实际项目中的应用

代理模式在实际项目中有着广泛的应用,特别是在需要增强对象功能、控制访问权限或实现延迟加载等场景中。以下是一些具体的应用示例:

  1. 数据库访问代理:在数据库访问层,我们通常会使用代理模式来封装数据库操作,实现连接池管理、事务控制、SQL日志记录等功能。代理对象负责处理与数据库的通信细节,而业务代码只需与代理对象交互,无需关心底层数据库的具体实现。

  2. 远程服务调用代理:在分布式系统中,服务之间的调用通常通过代理对象来实现。代理对象负责处理网络通信、序列化/反序列化、负载均衡等细节,使得服务调用更加简单和可靠。

  3. 文件访问代理:在文件系统中,我们可以使用代理模式来封装文件读写操作,实现文件加密、压缩、缓存等功能。代理对象负责处理文件的读写细节,而应用程序只需通过代理对象来访问文件。

  4. API网关:在微服务架构中,API网关通常作为服务调用的代理,负责处理认证、授权、限流、熔断等逻辑。API网关作为代理对象,将客户端的请求转发到相应的微服务,并处理响应结果。

  5. UI组件代理:在图形用户界面(GUI)开发中,代理模式可以用于封装复杂的UI组件,实现组件的延迟加载、动态替换或增强功能。代理对象可以管理组件的生命周期,并提供统一的接口供应用程序使用。

十一、代理模式的扩展与思考

代理模式作为一种经典的设计模式,在实际应用中有着广泛的应用场景。然而,随着技术的不断发展和业务需求的不断变化,我们也需要对代理模式进行扩展和思考。

  1. 异步代理:在处理耗时操作时,我们可以考虑使用异步代理来避免阻塞主线程。异步代理可以将操作放到后台线程中执行,并通过回调函数或Future对象等方式将结果返回给调用方。

  2. 动态代理与AOP(面向切面编程):动态代理是实现AOP的关键技术之一。通过动态代理,我们可以在不修改原有代码的情况下,为对象添加额外的行为(如日志记录、性能监控等)。这使得AOP成为一种强大的编程范式,能够极大地提高代码的可维护性和可扩展性。

  3. 代理模式的性能优化:虽然代理模式带来了很多好处,但也会引入一定的性能开销。因此,在实际应用中,我们需要对代理模式进行性能优化。例如,我们可以通过缓存代理对象、减少代理链的长度、优化网络通信等方式来降低性能开销。

  4. 代理模式与其他技术的结合:随着技术的发展,出现了很多新的编程范式和技术,如函数式编程、响应式编程等。我们可以思考如何将代理模式与这些新技术结合,以更好地满足业务需求和提高代码质量。

十二、总结与展望

代理模式作为一种经典的设计模式,在软件开发中发挥着重要的作用。通过合理地应用代理模式,我们可以实现对象的增强、访问控制、延迟加载等功能,提高代码的可维护性和可扩展性。然而,随着技术的不断发展和业务需求的不断变化,我们也需要对代理模式进行扩展和思考,以适应新的挑战和需求。未来,我们可以继续探索代理模式与其他技术的结合,以及如何更好地优化代理模式的性能,为构建高质量的软件系统提供有力支持。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/747630.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【gpt实践】50个提升工作效率的GPT指令

收集整理了50个工作不同场景中可能会用到的gpt指令&#xff0c;希望对大家有帮助。 1. 用「532规则」定制月度宣传规划 提示&#xff1a;“对于我的 [产品/服务] 在 [社交媒体平台上 ]定位 [我的目标受众]”&#xff0c;使用 5-3-2 规则制定 1 个月的社交媒体内容计划。” Pro…

关于I2C(Inter-Integrated Circuit)死锁及解决措施

I2C&#xff08;Inter-Integrated Circuit&#xff09;死锁是指两个或多个设备&#xff08;比如主设备和从设备&#xff09;在通信过程中&#xff0c;由于某种原因互相等待&#xff0c;导致无法正常进行通信的现象。这种死锁状态可能会导致整个系统的通信受阻&#xff0c;影响设…

K8S日志收集方案-EFK部署

EFK架构工作流程 部署说明 ECK (Elastic Cloud on Kubernetes)&#xff1a;2.7 Kubernetes&#xff1a;1.23.0 文件准备 crds.yaml 下载地址&#xff1a;https://download.elastic.co/downloads/eck/2.7.0/crds.yaml operator.yaml 下载地址&#xff1a;https://download.e…

性能出众的一区新算法|星鸦优化算法NOA原理及代码实现(Matlab)

文章来源于我的个人公众号&#xff1a;KAU的云实验台&#xff0c;主要更新智能优化算法的原理、应用、改进 CEC2005中的测试 本文KAU将介绍一个2023年发表在1区期刊KBS上的优化算法——星鸦优化算法(Nutcracker Optimization Algorithm&#xff0c;NOA)[1] 该算法由Mohamed …

一直被模仿,从未被超越

德国威步以及卓越的创新能力&#xff0c;成为业内不断被模仿的对象。德国威步自1989年创立35年以来&#xff0c;一直坚定地在软件保护及授权管理领域努力耕耘并不断创新和改进&#xff0c;拥抱互联网及软件开发技术的革新&#xff0c;完美融入并发展&#xff0c;虽然被其他竞争…

Github 2024-03-15 开源项目日报 Top10

根据Github Trendings的统计,今日(2024-03-15统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量TypeScript项目3Python项目3非开发语言项目2PHP项目1C#项目1Rust项目1《Hello 算法》:动画图解、一键运行的数据结构与算法教程 创建周期:476…

通过Rothko罗斯科绘画学习CSS盒子

本文章属于学习笔记&#xff0c;在https://www.freecodecamp.org/chinese/learn/2022/responsive-web-design/中练习 1、使用 padding 简写属性来增加两个元素之间的空间到。 .canvas {} .frame { padding:50px; }2、overflow 设置为 hidden - 将画布更改回其原始尺寸。overfl…

第十四届“中关村青联杯”全国研究生数学建模竞赛-A题:无人机在抢险救灾中的优化运用(续)

目录 6 问题三模型建立与求解 6.1 问题描述与分析 6.2 模型建立 6.3 模型求解

Discourse 分类图片

我们可以在 Discourse 上为分类添加图片。 进入分类编辑界面&#xff0c;然后选择 Image 标签。 在 Images 标签下&#xff0c;上传分类需要的图片。 图片大小 图片的大小是 Discourse 进行控制的&#xff0c;高度为 150 PX 像素。 如果上传的图片大于 150 px 的高度像素&…

C++ 虚函数与多态

定义宠物类 Pet &#xff0c;包含虚函数 speak &#xff0c;显示 " miao ! miao !"和" wang ! wang !"。 信息" How does a pet speak ?"; 主团数中定义 Pet 、 Cat 和 Dog 的对象&#xff0c;再定义 Pet 指针量 &#xff0c;分别指向 Pet Cat…

人工智能在未来的优势

人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;是一种模拟人类智能的技术&#xff0c;已经在现代科技中得到广泛应用&#xff0c;并且具有广阔的发展前景12。以下是人工智能在现代科技中的应用和未来发展趋势的介绍&#xff1a; 综上所述&#xff0c;…

零基础入门多媒体音频(2)-音频焦点2

说实话&#xff0c;android的代码是越来越难以阅读。业务函数里面狗皮膏药似的补丁与日俱增。继上篇简要介绍音频焦点的文章&#xff0c;这篇文章的主要内容是分析audiofocus的实现。看了一下午的相关代码都没找到做audiofocus策略的核心逻辑。目前能看懂的大概包含下面两个逻辑…

开源堡垒机Jumpserver安装教程

前言:堡垒机的应用场景 公司内有若干台服务器,既有windows的也有linux的, 提供有ERP,OA,Web,报表等等各种服务,往往需要远程登录到服务器上去做运维,但如果给root或者administrator权限,很容易出现不知道谁操作了的问题.如果不同人设置不同账号,又账号过多,权限不足等等其他问题…

高质量 Git 仓库汇总(持续更新,方便查看)

Leetcode https://github.com/kamyu104/LeetCode-Solutions Cmake https://github.com/viva64/pvs-studio-cmake-examples 3D目标检测 Awesome-3D-Object-Detection Awesome-3D-Object-Detection-for-Autonomous-Driving Cuda Code dbscan https://github.com/l3lackc…

外包就干了2个月,技术退步明显....

先说情况&#xff0c;大专毕业&#xff0c;18年通过校招进入湖南某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试&#xf…

【计算机视觉】二、图像形成:2、几何基元和几何变换:2D变换

文章目录 一、向量和矩阵的基本运算二、几何基元和变换1、几何基元(Geometric Primitives)2、几何变换(Geometric Transformations)1. 各种变换的关系2. 变换公式3. 2D变换的层次4. python实现 一、向量和矩阵的基本运算 【计算机视觉】二、图像形成&#xff1a;1、向量和矩阵…

echarts绘制 联系词(关键字)

<template><div><div>【关键词条】</div><div ref"target" class"w-full h-full" stylewidth:300px;height:300px></div></div> </template><script setup> import { ref, onMounted,watch } from …

使用docker-compose部署Redis集群

一、部署三主三从的Redis集群 分别为6个节点建立挂载目录&#xff0c;每个目录下建立数据、配置、日志文件夹。 docker-compose内容如下&#xff1a; version: 3 services:redis1:image: redis:6.2.3restart: alwaysports:- "6379:6379"- "16379:16379"v…

融入Facebook的世界:探索数字化社交的魅力

融入Facebook的世界&#xff0c;是一场数字化社交的奇妙之旅。在这个广袤的虚拟社交空间中&#xff0c;人们可以尽情展现自己、分享生活&#xff0c;与全球朋友、家人和同事保持紧密联系&#xff0c;共同探索社交互动的乐趣与魅力。让我们深入了解这个世界的魅力所在&#xff1…

基于SpringBoot+Vue的电商应用系统的设计与实现

1 绪论 1.1研究背景 当前社会各行业领域竞争压力非常大&#xff0c;随着当前时代的信息化&#xff0c;科学化发展&#xff0c;让社会各行业领域都争相使用新的信息技术&#xff0c;对行业内的各种相关数据进行科学化&#xff0c;规范化管理。这样的大环境让那些止步不前&…