当前位置: 首页 > news >正文

《设计模式之禅》笔记摘录 - 5.代理模式

代理模式的定义

代理模式(Proxy Pattern)是一个使用率非常高的模式,其定义如下:Provide a surrogate or placeholder for another object to control access to it. (为其他对象提供一种代理以控制对这个对象的访问。)

代理模式的通用类图:

代理模式也叫做委托模式,它是一项基本设计技巧。许多其他的模式,如状态模式、策略模式、访问者模式本质上是在更特殊的场合采用了委托模式,而且在日常的应用中,代理模式可以提供非常好的访问控制。在一些著名开源软件中也经常见到它的身影,如Struts2的Form元素映射就采用了代理模式(准确地说是动态代理模式)。我们先看一下类图中的三个角色的定义:

Subject抽象主题角色抽象主题类可以是抽象类也可以是接口,是一个最普通的业务类型定义,无特殊要求。

RealSubject具体主题角色做被委托角色、被代理角色。它才是冤大头,是业务逻辑的具体执行者。

Proxy代理主题角色也叫做委托类、代理类。它负责对真实角色的应用,把所有抽象主题类定义的方法限制委托给真实主题角色实现,并日在真实主题角色处理完毕前后做预处理和善后处理工作。

代理模式的应用

代理模式的优点

职责清晰。真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件事务,附带的结果就是编程简洁清晰。

高扩展性。角色是随时都会发生变化的,只要它实现了接口,甭管它如何变化,都逃不脱如来佛的手掌(接口),那我们的代理类完全就可以在不做任何修改的情况下使用。

智能化。在我们以上的讲解中还没有体现出来,不过在我们以下的动态代理章节中你就会看到代理的智能化有兴趣的读者也可以看看Struts是如何把表单元素映射到对象上的。

代理模式的使用场景

我相信第一次接触到代理模式的读者肯定很郁闷,为什么要用代理呀?想想现实世界吧,打官司为什么要找个律师?因为你不想参与中间过程的是是非非,只要完成自己的答辩就成,其他的比如事前调查、事后追查都由律师来搞定,这就是为了减轻你的负担。代理模式的使用景非常多,大家可以看看Spring AOP,这是一个非常典型的动态代理。

代理模式的扩展

普通代理

首先说普通代理,它的要求就是客户端只能访问代理角色,而不能访问真实角色,这是比简单的。

在该模式下,调用者只知代理而不用知道真实的角色是谁,屏蔽了真实角色的变更对高层模块的影响,真实的主题角色想怎么修改就怎么修改,对高层次的模块没有任何的影响,只要你实现了接口所对应的方法,该模式非常适合对扩展性要求较高的场。当然,在实际的项目中,一般都是通过约定来禁止new一个真实的角色,这也是一个非常好的方案。

注意普通代理模式的约束问题,尽量通过团队内的编程规范类约束,因为每一个主题类是可被重用的和可维护的,使用技术约束的方式对系统维护是一种非常不利的因素。

强制代理

强制代理在设计模式中比较另类,为什么这么说呢?一般的思维都是通过代理找到真实的角色,但是强制代理却是要“强制”,你必须通过真实角色查找到代理角色,否则你不能访问。

在接口上增加了一个getProxy方法,真实角色GamePlayer可以指定一个自己的代理,除了代理外谁都不能访问。

虽制代理的概念就是要从真实角色查找到代理角色,不允许且接访问真实角色。高层模块只要调用getProxy就可以访问真实角色的所有方法,它根本就不需要产生一个代理出来,代理的管理已经由真实角色自己完成。

代理是有个性的

一个类可以实现多个接口,完成不同任务的整合。也就是说代理类不仅仅可以实现主题接口,也可以实现其他接口完成不同的任务,而且代理的目的是在目标对象方法的基础上作增强,这种增强的本质通常就是对目标对象的方法进行拦截和过滤。

动态代理

什么是动态代理?动态代理是在实现阶段不用关心代理谁,而在运行阶段才指定代理哪一个对象。相对来说,自己写代理类的方式就是静态代理。

最佳实践

代理模式应用得非常广泛,大到一个系统框架、企业平台,小到代码片段、事务处理,稍不留意就用到代理模式。可能该模式是大家接触最多的模式,而且有了AOP大家写代理就更加简单了,有类似Spring AOP和AspectJ这样非常优秀的工具,拿来主义即可!不过,大家可以看看源代码,特别是调试时,只要看到类们$Proxy0这样的结构,你就应该知道这是一个动态代理了。

友情提醒,在学习AOP框架时,弄清楚几个名词就成:切面(Aspect)、切入点(JoinPoint)、通知(Advice)、织入(Weave)就足够了,理解了这几个名词,应用时你就可以游刃有余了!

http://www.dtcms.com/a/270604.html

相关文章:

  • Flutter基础(前端教程⑨-图片)
  • Robot之眼CMOS传感器静电防护指南
  • LeetCode热题100—— 32. 最长有效括号 (hard)
  • 零基础上手 Amazon DynamoDB:NoSQL 数据库服务的核心概念与快速搭建指南
  • Android-重学kotlin(协程源码第二阶段)新学习总结
  • 安全管理协议(SMP):配对流程、密钥生成与防中间人攻击——蓝牙面试核心考点精解
  • Qt自定义控件(9)——径向渐变QRadialGradient、圆锥渐变QConicalGradient
  • 华为OD机试_2025 B卷_观看文艺汇演问题(Python,100分)(附详细解题思路)
  • Amazon S3 对象存储服务深度解析:存储原理、应用场景与实战指南
  • Hexo + Butterfly + Vercel 完整个人Blog部署指南
  • 量子化学计算GPU化:ORCA与Gaussian的CUDA加速对比(电子积分计算中的Warpshuffle指令实战应用)
  • 如何给网页增加滚动到顶部的功能
  • 【具身智能】本地实时语音识别kaldi在正点原子RK3588上部署
  • Python标准库:时间与随机数全解析
  • python 异步编程事件循环的共享问题
  • 达梦:指定数据文件还原的路径
  • 【Linux | 网络】socket编程 - 使用TCP实现服务端向客户端提供简单的服务
  • Ragas的Prompt Object
  • 大数据在UI前端的应用深化:用户行为模式的挖掘与预测性分析
  • 网络信息安全学习笔记1----------网络信息安全概述
  • 2025年新材料与清洁能源国际会议(IACNMCE 2025)
  • 计算机网络实验——访问H3C网络设备
  • 题解:P13017 [GESP202506 七级] 线图
  • 【机器学习】BeamSearch算法
  • BEV感知2
  • python学习打卡:DAY 24 元组和OS模块
  • 5202年安装TensorFlow纪实
  • 【LeetCode207.课程表】以及变式
  • 暑假算法日记第五天
  • [2025CVPR]Mr. DETR:检测Transformer的多路由指导训练解析