当前位置: 首页 > 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.xdnf.cn/news/1090351.html

相关文章:

  • AI应用实践:制作一个支持超长计算公式的计算器,计算内容只包含加减乘除算法,保存在一个HTML文件中
  • 设计模式(行为型)-责任链模式
  • Flink Forward Asia 2025 主旨演讲精彩回顾
  • 两张图片对比clip功能
  • React 19 概览:新特性与生态系统变革
  • 1.1 ARMv8/ARMv9安全扩展
  • 网络安全之RCE分析与利用详情
  • 前端使用Web Cryptography API进行内容加密,几乎无法破解
  • 循环神经网络详解
  • 数据结构之位图和布隆过滤器
  • Web 前端框架选型:React、Vue 和 Angular 的对比与实践
  • [特殊字符] 突破小样本瓶颈:DataDream——用Stable Diffusion生成高质量分类数据集
  • “AI 曼哈顿计划”:科技竞赛还是人类挑战?
  • VUE混合开发,选哪个PHP框架最顺手?
  • 【Qt】Qt QML json处理
  • Qt的信号与槽(三)
  • uniapp小程序无感刷新token
  • 【数字后端】- Standard Cell Status
  • 【机器人】Aether 多任务世界模型 | 4D动态重建 | 视频预测 | 视觉规划
  • vue2中使用xgplayer播放流视频
  • Claude Code 开发使用技巧
  • 【Modern C++ Part7】_创建对象时使用()和{}的区别
  • 从0到1:Maven下载安装与配置全攻略
  • vcpkg交叉编译qt等过程记录(未完成)
  • 华为动态路由配置
  • Git基本操作1
  • git 报错fatal: refusing to merge unrelated histories
  • 城市地质大数据平台:透视地下空间,赋能智慧未来
  • 基于物联网的智能家居控制系统设计与实现
  • 从零开始的云计算生活——番外2,MySQL组复制