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

深入理解设计模式之代理模式

深入理解设计模式之代理模式

在软件开发的复杂体系中,我们常常会遇到这样的情况:需要控制对某个对象的访问,或者在访问对象前后添加一些额外的处理逻辑,又或者希望在不改变原对象代码的基础上扩展其功能。代理模式(Proxy Pattern)正是解决这些问题的有力工具,作为一种结构型设计模式,它在软件设计中扮演着重要的角色。

一、代理模式的定义

代理模式,简单来说,就是为其他对象提供一种代理以控制对这个对象的访问。在某些场景下,一个对象可能由于各种原因(如对象创建开销大、对象位于远程服务器等),不适合或者不能直接被客户端引用,而代理对象则可以在客户端和目标对象之间充当一个中介的角色,客户端通过代理对象来间接访问目标对象 。这就好比我们在生活中通过房产中介来寻找合适的房子,房产中介就是代理对象,它帮助我们与房东(目标对象)进行沟通和协调,控制我们对房东的访问,同时也为我们提供了一些额外的服务,如筛选房源、安排看房等。

二、代理模式的结构

代理模式主要包含以下三个核心角色:

  1. 抽象主题(Subject):这是一个抽象类或接口,它定义了真实主题和代理主题的共同接口,使得在任何使用真实主题的地方都可以使用代理主题。在上述房产中介的例子中,抽象主题可以是一个 “房屋租赁服务” 的接口,定义了寻找房源、签订合同等方法。
  1. 真实主题(RealSubject):实现了抽象主题接口,定义了真实对象所要实现的业务逻辑,是代理对象所代表的真实对象。继续以上述例子来说,房东就是真实主题,他拥有房屋的所有权,并负责提供房屋租赁的实际服务。
  1. 代理主题(Proxy):同样实现了抽象主题接口,持有一个对真实主题的引用。它在客户端和真实主题之间起到中介作用,控制对真实主题的访问,并可以在访问真实主题前后添加一些额外的操作,如权限验证、日志记录等。房产中介就是代理主题,它持有房东的相关信息,帮助租客与房东进行沟通和协调,并在租赁过程中提供一些额外的服务,如协助租客了解房屋周边环境、办理租赁手续等。

三、代理模式的类型

根据代理对象的创建时机和方式,代理模式可以分为静态代理和动态代理:

  1. 静态代理:在编译期就已经确定代理类和目标类的关系,代理类是手动编写的,并且在程序运行前就已经存在。静态代理的优点是实现简单,容易理解;缺点是当需要代理多个不同的对象时,需要编写多个代理类,代码量较大,维护起来比较困难。例如,在一个电商系统中,如果每个商品都需要一个代理类来进行库存检查和价格调整,那么就需要编写大量的代理类。
  1. 动态代理:在运行时通过反射机制动态地创建代理类,代理类的创建不需要手动编写,而是根据实际需求在运行时动态生成。动态代理的优点是可以灵活地代理多个不同的对象,代码量较少,维护方便;缺点是实现相对复杂,对反射机制的理解和运用要求较高。例如,在一个权限管理系统中,可以使用动态代理来为不同的业务方法添加权限验证功能,根据用户的角色和权限动态地生成代理类。

四、代理模式的优缺点

  1. 优点
    • 职责清晰:真实主题专注于实现核心业务逻辑,代理主题负责处理与访问控制、额外功能添加等相关的事务,使得代码的职责更加清晰,易于维护和扩展。比如在一个文件管理系统中,文件读写操作由真实主题负责,而权限验证、日志记录等功能由代理主题实现。
    • 保护目标对象:代理对象可以在客户端和目标对象之间起到中介的作用,对客户端的访问进行控制和过滤,从而保护目标对象不被非法访问或滥用。例如,在一个数据库系统中,通过代理对象可以限制用户对敏感数据的访问权限。
    • 增强功能:在不修改目标对象代码的前提下,通过代理对象可以方便地为目标对象添加新的功能,如日志记录、缓存、事务管理等。例如,在一个网络请求系统中,可以通过代理对象为请求添加缓存功能,提高系统的性能。
    • 延迟加载:对于创建开销较大或者初始化耗时的对象,可以使用代理对象来延迟对象的创建和初始化,直到真正需要使用时才创建,从而提高系统的性能和资源利用率。例如,在一个图形绘制系统中,对于复杂的图形对象,可以使用代理对象来延迟其创建,直到需要显示时才进行创建。
  1. 缺点
    • 增加系统复杂度:代理模式引入了代理对象,增加了系统的抽象层次和复杂性,特别是在动态代理的情况下,由于涉及到反射机制,代码的可读性和可维护性可能会受到一定的影响。
    • 性能开销:在通过代理对象访问目标对象时,会增加一些额外的开销,如方法调用的转发、反射操作等,这可能会对系统的性能产生一定的影响,尤其是在对性能要求较高的场景下需要谨慎使用。
    • 接口一致性维护:代理对象和目标对象需要实现相同的接口,当接口发生变化时,需要同时修改代理对象和目标对象的代码,以保持接口的一致性,这增加了代码维护的难度。

五、代理模式的应用场景

  1. 权限控制:在访问某些敏感资源或执行某些关键操作之前,通过代理对象检查用户的权限,只有具有相应权限的用户才能访问或执行。例如,在一个企业信息管理系统中,对员工的工资查询、修改等操作可以通过代理对象进行权限验证,只有人力资源部门的员工和相关领导才能进行这些操作。
  1. 远程代理:在分布式系统中,当需要访问远程服务器上的对象时,可以使用远程代理来隐藏对象存在于不同地址空间的事实,为远程对象提供一个本地代表。远程代理负责处理与远程对象的通信,包括数据的序列化、传输和反序列化等操作,使得客户端可以像访问本地对象一样访问远程对象。例如,在一个电商系统中,订单处理服务可能部署在远程服务器上,客户端可以通过远程代理来调用订单处理服务,而无需关心远程通信的细节。
  1. 虚拟代理:对于创建开销大或者初始化耗时的对象,可以使用虚拟代理来延迟对象的创建和初始化。虚拟代理在客户端请求时,先返回一个简单的代理对象,当真正需要使用目标对象时,再创建并初始化目标对象。例如,在一个图像浏览系统中,对于大尺寸的图片,可以使用虚拟代理来延迟图片的加载,当用户需要查看图片时,再加载图片,提高系统的响应速度。
  1. 缓存代理:在访问某些频繁使用且数据相对稳定的资源时,可以使用缓存代理来缓存资源的结果,当再次访问时,直接从缓存中获取结果,而无需重新获取或计算,从而提高系统的性能。例如,在一个新闻网站中,对于热门新闻的内容,可以使用缓存代理来缓存,当用户再次访问时,直接从缓存中获取新闻内容,减少数据库的查询压力。
  1. 智能引用:在对象被访问时,通过代理对象执行一些额外的操作,如记录对象的访问次数、检查对象的状态等。例如,在一个数据库连接池系统中,可以使用代理对象来记录每个数据库连接的使用次数,当连接使用次数达到一定阈值时,进行连接的回收或更新。

六、代理模式的代码示例

静态代理示例

首先定义抽象主题接口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样式

解决问题&#xff1a; 1.选中文案样式&#xff0c;比如字体颜色 2.修改分割线颜色 3.多列时&#xff0c;修改两边间距让其平分 展示效果&#xff1a; 代码如下 <template><u-popup :show"showPicker" :safeAreaInsetBottom"false" close&quo…...

HDFS Java 客户端 API

一、基本调用 Configuration 配置对象类&#xff0c;用于加载或设置参数属性 FileSystem 文件系统对象基类。针对不同文件系统有不同具体实现。该类封装了文件系统的相关操作方法。 1. maven依赖pom.xml文件 <dependency><groupId>org.apache.hadoop</groupId&g…...

【华三】STP的角色选举(一文讲透)

【华三】STP的角色选举 一、引言二、STP基础概念扫盲三、根桥选举过程详解四、根端口选举过程详解五、指定端口选举过程详解六、阻塞端口七、总结与配置建议七、附录**1. BPDU字段结构图&#xff08;文字描述&#xff09;****2. 华三STP常用命令速查表** 文章总结 一、引言 在…...

【C#零基础从入门到精通】(二十六)——C#三大特征-多态详解

【C#零基础从入门到精通】(二十六)——C#三大特征-多态详解 在 C# 中,多态是面向对象编程的重要特性之一,它允许不同的对象对同一消息做出不同的响应。多态可以分为静态多态和动态多态,下面将详细介绍它们以及各自包含的知识点。 多态概述 多态性使得代码更加灵活、可扩展…...

宇树科技13家核心零部件供应商梳理!

2025年2月6日&#xff0c;摩根士丹利&#xff08;Morgan Stanley&#xff09;发布最新人形机器人研报&#xff1a;Humanoid 100: Mapping the Humanoid Robot Value Chain&#xff08;人形机器人100&#xff1a;全球人形机器人产业链梳理&#xff09;。 Humanoid 100清单清单中…...

Java集合框架全解析:从LinkedHashMap到TreeMap与HashSet面试题实战

一、LinkedHashMap ①LinkedHashMap集合和HashMap集合的用法完全相同。 ②不过LinkedHashMap可以保证插入顺序。 ③LinkedHashMap集合因为可以保证插入顺序&#xff0c;因此效率比HashMap低一些。 ④LinkedHashMap是如何保证插入顺序的&#xff1f; 底层采用了双向链表来记…...

goland无法debug项目

1、其实个原因是因为正在使用的Delve调试器版本太旧&#xff0c;无法兼容当前的Go语言版本1.2。Delve是Go语言的一个调试工具&#xff0c;用于提供源码级别的调试功能。Go语言每隔一段时间会发布新版本&#xff0c;而相应的调试器Delve也可能会更新以提供新的特性或修复已知问题…...

深入探索 DeepSeek 在数据分析与可视化中的应用

在数据驱动的时代&#xff0c;快速且准确地分析和呈现数据对于企业和个人都至关重要。DeepSeek 作为一款先进的人工智能工具&#xff0c;凭借其强大的数据处理和可视化能力&#xff0c;正在革新数据分析的方式。 1. 数据预处理与清洗 在进行数据分析前&#xff0c;数据预处理…...

python面试题整理

Python 如何处理异常&#xff1f; Python中&#xff0c;使用try 和 except 关键字来捕获和处理异常 try 块中放置可能会引发异常的代码&#xff0c;然后在except块中处理这些异常。 能补充一下finally的作用吗&#xff1f; finally 块中的代码无论是否发生异常都会执行&#xf…...

大型装备故障诊断解决方案

大型装备故障诊断解决方案 方案背景 在全球航空工业迅猛发展的背景下&#xff0c;我国在军用和民用飞机自主研发制造领域取得了显著成就。尤其是在国家大力支持下&#xff0c;国内飞机制造企业攻克了诸多关键技术难题&#xff0c;实现了从设计研发到生产制造再到售后保障的完整…...

基于SpringBoot+vue+uniapp的智慧旅游小程序+LW示例参考

系列文章目录 1.基于SSM的洗衣房管理系统原生微信小程序LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统LW参考示例 3.基于SpringBootVue的企业人事管理系统LW参考示例 4.基于SSM的高校实验室管理系统LW参考示例 5.基于SpringBoot的二手数码回收系统原生微信小程序LW参考示…...

小怿学习日记(七) | Unreal引擎灯光架构

灯光的布局对于HMI场景中车模的展示效果有着举足轻重的地位。本篇内容将简单介绍ES3.1的相关知识&#xff0c;再深入了解Unreal引擎中车模的灯光以及灯光架构。 一、关于ES3.1 1.1 什么是ES3.1 ES3.1这个概念对于美术的同学可能比较陌生&#xff0c;ES3.1指的是OpenGL ES3.1&…...

网络运维学习笔记 013网工初级(HCIA-Datacom与CCNA-EI)DHCP动态主机配置协议(此处只讲华为)

文章目录 DHCP&#xff08;Dynamic Host Configuration Protocol&#xff0c;动态主机配置协议&#xff09;网关配置DHCP服务器配置如果没有DHCP服务器&#xff0c;只在网关上做DHCP服务器&#xff1a; DHCP&#xff08;Dynamic Host Configuration Protocol&#xff0c;动态主…...

javaEE-14.spring MVC练习

目录 1.加法计算器 需求分析: 前端页面代码: 后端代码实现功能: 调整前端页面代码: 进行测试: 2.用户登录 需求分析: 定义接口: 1.登录数据校验接口: 2.查询登录用户接口: 前端代码: 后端代码: 调整前端代码: 测试/查错因 后端: 前端: lombok工具 1.引入依赖…...

uniapp 对接腾讯云IM群组成员管理(增删改查)

UniApp 实战&#xff1a;腾讯云IM群组成员管理&#xff08;增删改查&#xff09; 一、前言 在社交类App开发中&#xff0c;群组成员管理是核心功能之一。本文将基于UniApp框架&#xff0c;结合腾讯云IM SDK&#xff0c;详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)

引言&#xff1a;为什么 Eureka 依然是存量系统的核心&#xff1f; 尽管 Nacos 等新注册中心崛起&#xff0c;但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制&#xff0c;是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台

🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

NPOI操作EXCEL文件 ——CAD C# 二次开发

缺点:dll.版本容易加载错误。CAD加载插件时&#xff0c;没有加载所有类库。插件运行过程中用到某个类库&#xff0c;会从CAD的安装目录找&#xff0c;找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库&#xff0c;就用插件程序加载进…...

Qemu arm操作系统开发环境

使用qemu虚拟arm硬件比较合适。 步骤如下&#xff1a; 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载&#xff0c;下载地址&#xff1a;https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...

【实施指南】Android客户端HTTPS双向认证实施指南

&#x1f510; 一、所需准备材料 证书文件&#xff08;6类核心文件&#xff09; 类型 格式 作用 Android端要求 CA根证书 .crt/.pem 验证服务器/客户端证书合法性 需预置到Android信任库 服务器证书 .crt 服务器身份证明 客户端需持有以验证服务器 客户端证书 .crt 客户端身份…...

对象回调初步研究

_OBJECT_TYPE结构分析 在介绍什么是对象回调前&#xff0c;首先要熟悉下结构 以我们上篇线程回调介绍过的导出的PsProcessType 结构为例&#xff0c;用_OBJECT_TYPE这个结构来解析它&#xff0c;0x80处就是今天要介绍的回调链表&#xff0c;但是先不着急&#xff0c;先把目光…...