深入理解设计模式之代理模式
深入理解设计模式之代理模式
在软件开发的复杂体系中,我们常常会遇到这样的情况:需要控制对某个对象的访问,或者在访问对象前后添加一些额外的处理逻辑,又或者希望在不改变原对象代码的基础上扩展其功能。代理模式(Proxy Pattern)正是解决这些问题的有力工具,作为一种结构型设计模式,它在软件设计中扮演着重要的角色。
一、代理模式的定义
代理模式,简单来说,就是为其他对象提供一种代理以控制对这个对象的访问。在某些场景下,一个对象可能由于各种原因(如对象创建开销大、对象位于远程服务器等),不适合或者不能直接被客户端引用,而代理对象则可以在客户端和目标对象之间充当一个中介的角色,客户端通过代理对象来间接访问目标对象 。这就好比我们在生活中通过房产中介来寻找合适的房子,房产中介就是代理对象,它帮助我们与房东(目标对象)进行沟通和协调,控制我们对房东的访问,同时也为我们提供了一些额外的服务,如筛选房源、安排看房等。
二、代理模式的结构
代理模式主要包含以下三个核心角色:
- 抽象主题(Subject):这是一个抽象类或接口,它定义了真实主题和代理主题的共同接口,使得在任何使用真实主题的地方都可以使用代理主题。在上述房产中介的例子中,抽象主题可以是一个 “房屋租赁服务” 的接口,定义了寻找房源、签订合同等方法。
- 真实主题(RealSubject):实现了抽象主题接口,定义了真实对象所要实现的业务逻辑,是代理对象所代表的真实对象。继续以上述例子来说,房东就是真实主题,他拥有房屋的所有权,并负责提供房屋租赁的实际服务。
- 代理主题(Proxy):同样实现了抽象主题接口,持有一个对真实主题的引用。它在客户端和真实主题之间起到中介作用,控制对真实主题的访问,并可以在访问真实主题前后添加一些额外的操作,如权限验证、日志记录等。房产中介就是代理主题,它持有房东的相关信息,帮助租客与房东进行沟通和协调,并在租赁过程中提供一些额外的服务,如协助租客了解房屋周边环境、办理租赁手续等。
三、代理模式的类型
根据代理对象的创建时机和方式,代理模式可以分为静态代理和动态代理:
- 静态代理:在编译期就已经确定代理类和目标类的关系,代理类是手动编写的,并且在程序运行前就已经存在。静态代理的优点是实现简单,容易理解;缺点是当需要代理多个不同的对象时,需要编写多个代理类,代码量较大,维护起来比较困难。例如,在一个电商系统中,如果每个商品都需要一个代理类来进行库存检查和价格调整,那么就需要编写大量的代理类。
- 动态代理:在运行时通过反射机制动态地创建代理类,代理类的创建不需要手动编写,而是根据实际需求在运行时动态生成。动态代理的优点是可以灵活地代理多个不同的对象,代码量较少,维护方便;缺点是实现相对复杂,对反射机制的理解和运用要求较高。例如,在一个权限管理系统中,可以使用动态代理来为不同的业务方法添加权限验证功能,根据用户的角色和权限动态地生成代理类。
四、代理模式的优缺点
- 优点
-
- 职责清晰:真实主题专注于实现核心业务逻辑,代理主题负责处理与访问控制、额外功能添加等相关的事务,使得代码的职责更加清晰,易于维护和扩展。比如在一个文件管理系统中,文件读写操作由真实主题负责,而权限验证、日志记录等功能由代理主题实现。
-
- 保护目标对象:代理对象可以在客户端和目标对象之间起到中介的作用,对客户端的访问进行控制和过滤,从而保护目标对象不被非法访问或滥用。例如,在一个数据库系统中,通过代理对象可以限制用户对敏感数据的访问权限。
-
- 增强功能:在不修改目标对象代码的前提下,通过代理对象可以方便地为目标对象添加新的功能,如日志记录、缓存、事务管理等。例如,在一个网络请求系统中,可以通过代理对象为请求添加缓存功能,提高系统的性能。
-
- 延迟加载:对于创建开销较大或者初始化耗时的对象,可以使用代理对象来延迟对象的创建和初始化,直到真正需要使用时才创建,从而提高系统的性能和资源利用率。例如,在一个图形绘制系统中,对于复杂的图形对象,可以使用代理对象来延迟其创建,直到需要显示时才进行创建。
- 缺点
-
- 增加系统复杂度:代理模式引入了代理对象,增加了系统的抽象层次和复杂性,特别是在动态代理的情况下,由于涉及到反射机制,代码的可读性和可维护性可能会受到一定的影响。
-
- 性能开销:在通过代理对象访问目标对象时,会增加一些额外的开销,如方法调用的转发、反射操作等,这可能会对系统的性能产生一定的影响,尤其是在对性能要求较高的场景下需要谨慎使用。
-
- 接口一致性维护:代理对象和目标对象需要实现相同的接口,当接口发生变化时,需要同时修改代理对象和目标对象的代码,以保持接口的一致性,这增加了代码维护的难度。
五、代理模式的应用场景
- 权限控制:在访问某些敏感资源或执行某些关键操作之前,通过代理对象检查用户的权限,只有具有相应权限的用户才能访问或执行。例如,在一个企业信息管理系统中,对员工的工资查询、修改等操作可以通过代理对象进行权限验证,只有人力资源部门的员工和相关领导才能进行这些操作。
- 远程代理:在分布式系统中,当需要访问远程服务器上的对象时,可以使用远程代理来隐藏对象存在于不同地址空间的事实,为远程对象提供一个本地代表。远程代理负责处理与远程对象的通信,包括数据的序列化、传输和反序列化等操作,使得客户端可以像访问本地对象一样访问远程对象。例如,在一个电商系统中,订单处理服务可能部署在远程服务器上,客户端可以通过远程代理来调用订单处理服务,而无需关心远程通信的细节。
- 虚拟代理:对于创建开销大或者初始化耗时的对象,可以使用虚拟代理来延迟对象的创建和初始化。虚拟代理在客户端请求时,先返回一个简单的代理对象,当真正需要使用目标对象时,再创建并初始化目标对象。例如,在一个图像浏览系统中,对于大尺寸的图片,可以使用虚拟代理来延迟图片的加载,当用户需要查看图片时,再加载图片,提高系统的响应速度。
- 缓存代理:在访问某些频繁使用且数据相对稳定的资源时,可以使用缓存代理来缓存资源的结果,当再次访问时,直接从缓存中获取结果,而无需重新获取或计算,从而提高系统的性能。例如,在一个新闻网站中,对于热门新闻的内容,可以使用缓存代理来缓存,当用户再次访问时,直接从缓存中获取新闻内容,减少数据库的查询压力。
- 智能引用:在对象被访问时,通过代理对象执行一些额外的操作,如记录对象的访问次数、检查对象的状态等。例如,在一个数据库连接池系统中,可以使用代理对象来记录每个数据库连接的使用次数,当连接使用次数达到一定阈值时,进行连接的回收或更新。
六、代理模式的代码示例
静态代理示例
首先定义抽象主题接口Subject:
// 抽象主题接口public interface Subject {void request();}
然后定义真实主题类RealSubject:
// 真实主题类public class RealSubject implements Subject {@Overridepublic void request() {System.out.println("RealSubject: handling request.");}}
接着定义代理主题类Proxy:
// 代理主题类public class Proxy implements Subject {private RealSubject realSubject;public Proxy() {this.realSubject = new RealSubject();}@Overridepublic void request() {System.out.println("Proxy: before request.");realSubject.request();System.out.println("Proxy: after request.");}}
最后在客户端进行测试:
public class Client {public static void main(String[] args) {Subject proxy = new Proxy();proxy.request();}}
动态代理示例
首先定义抽象主题接口Subject和真实主题类RealSubject,与静态代理示例相同。
然后定义代理处理器类InvocationHandlerImpl:
import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;// 代理处理器类public class InvocationHandlerImpl implements InvocationHandler {private Object target;public InvocationHandlerImpl(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("InvocationHandler: before method invocation.");Object result = method.invoke(target, args);System.out.println("InvocationHandler: after method invocation.");return result;}}
最后在客户端进行测试:
import java.lang.reflect.Proxy;public class Client {public static void main(String[] args) {RealSubject realSubject = new RealSubject();Subject proxy = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(),realSubject.getClass().getInterfaces(),new InvocationHandlerImpl(realSubject));proxy.request();}}
上述代码分别展示了静态代理和动态代理的实现方式,通过代理模式可以在不修改真实主题类代码的基础上,为其添加额外的功能,并且可以灵活地控制对真实主题的访问。
通过对代理模式的深入了解,我们可以看到它在软件设计中具有广泛的应用场景和强大的功能。在实际项目开发中,合理运用代理模式能够使我们的代码更加灵活、可维护和可扩展,提升软件系统的质量和开发效率。如果你对代理模式还有其他疑问,比如在不同场景下如何选择合适的代理类型,欢迎随时与我交流。
相关文章:
深入理解设计模式之代理模式
深入理解设计模式之代理模式 在软件开发的复杂体系中,我们常常会遇到这样的情况:需要控制对某个对象的访问,或者在访问对象前后添加一些额外的处理逻辑,又或者希望在不改变原对象代码的基础上扩展其功能。代理模式(Pr…...
Golang | 每日一练 (3)
💢欢迎来到张胤尘的技术站 💥技术如江河,汇聚众志成。代码似星辰,照亮行征程。开源精神长,传承永不忘。携手共前行,未来更辉煌💥 文章目录 Golang | 每日一练 (3)题目参考答案map 实现原理hmapb…...
企业数据集成:实现高效调拨出库自动化
调拨出库对接调出单-v:旺店通企业奇门数据集成到用友BIP 在企业信息化管理中,数据的高效流转和准确对接是实现业务流程自动化的关键。本文将分享一个实际案例,展示如何通过轻易云数据集成平台,将旺店通企业奇门的数据无缝集成到用…...
提效10倍:基于Paimon+Dolphin湖仓一体新架构在阿里妈妈品牌业务探索实践
1. 业务背景 阿里妈妈品牌广告数据包括投放引擎、下发、曝光、点击等日志,面向运筹调控、算法特征、分析报表、诊断监控等应用场景,进行了品牌数仓能力建设。随着业务发展,基于Lambda架构的数仓开发模式,缺陷日益突出:…...
Deepseek快速做PPT
背景: DeepSeek大纲生成 → Kimi结构化排版 → 数据审查,细节调整 DeepSeek 拥有深度思考能力,擅长逻辑构建与内容生成,它会根据我们的问题进行思考,其深度思考能力当前测试下来,不愧为国内No.1,而且还会把中间的思考过程展示出来,大多时候会给出很多我们意想不到的思…...
论文解读 | AAAI'25 Cobra:多模态扩展的大型语言模型,以实现高效推理
点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入! 点击 阅读原文 观看作者讲解回放! 个人信息 作者:赵晗,浙江大学-西湖大学联合培养博士生 内容简介 近年来,在各个领域应用多模态大语言模型(MLLMs&…...
uniapp修改picker-view样式
解决问题: 1.选中文案样式,比如字体颜色 2.修改分割线颜色 3.多列时,修改两边间距让其平分 展示效果: 代码如下 <template><u-popup :show"showPicker" :safeAreaInsetBottom"false" close&quo…...
HDFS Java 客户端 API
一、基本调用 Configuration 配置对象类,用于加载或设置参数属性 FileSystem 文件系统对象基类。针对不同文件系统有不同具体实现。该类封装了文件系统的相关操作方法。 1. maven依赖pom.xml文件 <dependency><groupId>org.apache.hadoop</groupId&g…...
【华三】STP的角色选举(一文讲透)
【华三】STP的角色选举 一、引言二、STP基础概念扫盲三、根桥选举过程详解四、根端口选举过程详解五、指定端口选举过程详解六、阻塞端口七、总结与配置建议七、附录**1. BPDU字段结构图(文字描述)****2. 华三STP常用命令速查表** 文章总结 一、引言 在…...
【C#零基础从入门到精通】(二十六)——C#三大特征-多态详解
【C#零基础从入门到精通】(二十六)——C#三大特征-多态详解 在 C# 中,多态是面向对象编程的重要特性之一,它允许不同的对象对同一消息做出不同的响应。多态可以分为静态多态和动态多态,下面将详细介绍它们以及各自包含的知识点。 多态概述 多态性使得代码更加灵活、可扩展…...
宇树科技13家核心零部件供应商梳理!
2025年2月6日,摩根士丹利(Morgan Stanley)发布最新人形机器人研报:Humanoid 100: Mapping the Humanoid Robot Value Chain(人形机器人100:全球人形机器人产业链梳理)。 Humanoid 100清单清单中…...
Java集合框架全解析:从LinkedHashMap到TreeMap与HashSet面试题实战
一、LinkedHashMap ①LinkedHashMap集合和HashMap集合的用法完全相同。 ②不过LinkedHashMap可以保证插入顺序。 ③LinkedHashMap集合因为可以保证插入顺序,因此效率比HashMap低一些。 ④LinkedHashMap是如何保证插入顺序的? 底层采用了双向链表来记…...
goland无法debug项目
1、其实个原因是因为正在使用的Delve调试器版本太旧,无法兼容当前的Go语言版本1.2。Delve是Go语言的一个调试工具,用于提供源码级别的调试功能。Go语言每隔一段时间会发布新版本,而相应的调试器Delve也可能会更新以提供新的特性或修复已知问题…...
深入探索 DeepSeek 在数据分析与可视化中的应用
在数据驱动的时代,快速且准确地分析和呈现数据对于企业和个人都至关重要。DeepSeek 作为一款先进的人工智能工具,凭借其强大的数据处理和可视化能力,正在革新数据分析的方式。 1. 数据预处理与清洗 在进行数据分析前,数据预处理…...
python面试题整理
Python 如何处理异常? Python中,使用try 和 except 关键字来捕获和处理异常 try 块中放置可能会引发异常的代码,然后在except块中处理这些异常。 能补充一下finally的作用吗? finally 块中的代码无论是否发生异常都会执行…...
大型装备故障诊断解决方案
大型装备故障诊断解决方案 方案背景 在全球航空工业迅猛发展的背景下,我国在军用和民用飞机自主研发制造领域取得了显著成就。尤其是在国家大力支持下,国内飞机制造企业攻克了诸多关键技术难题,实现了从设计研发到生产制造再到售后保障的完整…...
基于SpringBoot+vue+uniapp的智慧旅游小程序+LW示例参考
系列文章目录 1.基于SSM的洗衣房管理系统原生微信小程序LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统LW参考示例 3.基于SpringBootVue的企业人事管理系统LW参考示例 4.基于SSM的高校实验室管理系统LW参考示例 5.基于SpringBoot的二手数码回收系统原生微信小程序LW参考示…...
小怿学习日记(七) | Unreal引擎灯光架构
灯光的布局对于HMI场景中车模的展示效果有着举足轻重的地位。本篇内容将简单介绍ES3.1的相关知识,再深入了解Unreal引擎中车模的灯光以及灯光架构。 一、关于ES3.1 1.1 什么是ES3.1 ES3.1这个概念对于美术的同学可能比较陌生,ES3.1指的是OpenGL ES3.1&…...
网络运维学习笔记 013网工初级(HCIA-Datacom与CCNA-EI)DHCP动态主机配置协议(此处只讲华为)
文章目录 DHCP(Dynamic Host Configuration Protocol,动态主机配置协议)网关配置DHCP服务器配置如果没有DHCP服务器,只在网关上做DHCP服务器: DHCP(Dynamic Host Configuration Protocol,动态主…...
javaEE-14.spring MVC练习
目录 1.加法计算器 需求分析: 前端页面代码: 后端代码实现功能: 调整前端页面代码: 进行测试: 2.用户登录 需求分析: 定义接口: 1.登录数据校验接口: 2.查询登录用户接口: 前端代码: 后端代码: 调整前端代码: 测试/查错因 后端: 前端: lombok工具 1.引入依赖…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
conda相比python好处
Conda 作为 Python 的环境和包管理工具,相比原生 Python 生态(如 pip 虚拟环境)有许多独特优势,尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处: 一、一站式环境管理:…...
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...
【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...
基于SpringBoot在线拍卖系统的设计和实现
摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...
Java数值运算常见陷阱与规避方法
整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...
Visual Studio Code 扩展
Visual Studio Code 扩展 change-case 大小写转换EmmyLua for VSCode 调试插件Bookmarks 书签 change-case 大小写转换 https://marketplace.visualstudio.com/items?itemNamewmaurer.change-case 选中单词后,命令 changeCase.commands 可预览转换效果 EmmyLua…...
大数据治理的常见方式
大数据治理的常见方式 大数据治理是确保数据质量、安全性和可用性的系统性方法,以下是几种常见的治理方式: 1. 数据质量管理 核心方法: 数据校验:建立数据校验规则(格式、范围、一致性等)数据清洗&…...
ArcGIS Pro+ArcGIS给你的地图加上北回归线!
今天来看ArcGIS Pro和ArcGIS中如何给制作的中国地图或者其他大范围地图加上北回归线。 我们将在ArcGIS Pro和ArcGIS中一同介绍。 1 ArcGIS Pro中设置北回归线 1、在ArcGIS Pro中初步设置好经纬格网等,设置经线、纬线都以10间隔显示。 2、需要插入背会归线…...
