设计模式 结构型 代理模式(Proxy Pattern)与 常见技术框架应用 解析

代理模式(Proxy Pattern)是一种常见的设计模式,在软件开发中有着广泛的应用。其核心思想是通过创建一个代理类来控制对另一个对象的访问,从而实现对目标对象功能的扩展、保护或其他附加操作。
一、核心思想
代理模式的核心思想在于提供一个代理对象,作为客户端与目标对象之间的中介。客户端并不直接调用目标对象的方法,而是通过调用代理对象的方法来间接调用目标对象的方法。这样可以在调用目标对象方法之前或之后添加额外的逻辑,如权限检查、日志记录、事务处理等。
二、定义与结构
定义:代理模式为其他对象提供一种代理以控制对这个对象的访问。
结构:
- 抽象角色(Subject):通过接口或抽象类声明真实角色实现的业务方法。
- 代理角色(Proxy):实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
- 真实角色(Real Subject):实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。
角色
在代理模式中,通常涉及以下三个角色:
- 抽象主题(Subject):定义了真实主题和代理主题的共同接口。
- 真实主题(Real Subject):实现了具体的业务逻辑,是代理模式中被代理的对象。
- 代理主题(Proxy Subject):持有对真实主题的引用,可以在调用真实主题之前或之后执行附加的操作。
三、实现步骤及代码示例
以下是通过Java技术框架实现代理模式的详细步骤及代码示例:
静态代理:
- 定义抽象主题接口:
public interface Subject {void request();
}
- 实现真实主题类:
public class RealSubject implements Subject {@Overridepublic void request() {System.out.println("RealSubject: Handling request.");}
}
- 实现代理主题类:
public class ProxySubject implements Subject {private RealSubject realSubject;@Overridepublic void request() {if (realSubject == null) {realSubject = new RealSubject();}preRequest();realSubject.request();postRequest();}private void preRequest() {System.out.println("ProxySubject: Preparing for request.");}private void postRequest() {System.out.println("ProxySubject: Finishing up request.");}
}
- 客户端代码:
public class Client {public static void main(String[] args) {Subject subject = new ProxySubject();subject.request();}
}
动态代理:
- 定义抽象主题接口(同上)。
- 实现真实主题类(同上)。
- 创建InvocationHandler实现类:
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;public class ProxyHandler implements InvocationHandler {private final Object target;public ProxyHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {preRequest();Object result = method.invoke(target, args);postRequest();return result;}private void preRequest() {System.out.println("ProxySubject: Preparing for request.");}private void postRequest() {System.out.println("ProxySubject: Finishing up request.");}
}
- 客户端代码:
import java.lang.reflect.Proxy;public class Client {public static void main(String[] args) {RealSubject realSubject = new RealSubject();InvocationHandler handler = new ProxyHandler(realSubject);Subject subject = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(),realSubject.getClass().getInterfaces(),handler);subject.request();}
}
四、常见技术框架应用
1、网络请求代理服务器
在网络请求中,可能会使用代理服务器。假设我们有一个简单的网络请求接口和实现:
- 定义抽象主题(网络请求接口):
interface NetworkRequest {String request(String url);
}
- 真实主题(实际的网络请求实现):
class RealNetworkRequest implements NetworkRequest {@Overridepublic String request(String url) {System.out.println("Sending request to " + url);// 这里可以是实际的网络请求代码,比如使用HttpURLConnection等return "Response from " + url;}
}
- 代理(带有缓存功能的网络请求代理):
import java.util.HashMap;
import java.util.Map;class CachedNetworkRequestProxy implements NetworkRequest {private RealNetworkRequest realRequest;private Map<String, String> cache = new HashMap<>();@Overridepublic String request(String url) {if (cache.containsKey(url)) {System.out.println("Retrieving from cache for " + url);return cache.get(url);} else {if (realRequest == null) {realRequest = new RealNetworkRequest();}String response = realRequest.request(url);cache.put(url, response);return response;}}
}
- 使用示例:
NetworkRequest request = new CachedNetworkRequestProxy();
System.out.println(request.request("https://example.com"));
System.out.println(request.request("https://example.com"));
这里代理对象CachedNetworkRequestProxy在第一次请求时会调用真实对象RealNetworkRequest进行网络请求,然后将结果缓存起来。之后相同的请求就直接从缓存中获取,减少了网络请求的次数。
2、Spring AOP
在Java中,代理模式也很常见,特别是在Spring框架中。以下是一个简单的Spring AOP(面向切面编程)示例:
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;// Service interface
public interface SimpleService {void perform();
}// Service implementation
public class SimpleServiceImpl implements SimpleService {@Overridepublic void perform() {System.out.println("Performing service operation");}
}// Before advice
public class LoggingBeforeAdvice implements MethodBeforeAdvice {@Overridepublic void before(Method method, Object[] args, Object target) throws Throwable {System.out.println("Logging before method: " + method.getName());}
}// Client code
public class ProxyDemo {public static void main(String[] args) {SimpleService service = new SimpleServiceImpl();ProxyFactory factory = new ProxyFactory();factory.setTarget(service);factory.addAdvice(new LoggingBeforeAdvice());SimpleService proxy = (SimpleService) factory.getProxy();proxy.perform(); // Output: Logging before method: perform \n Performing service operation}
}
在这个例子中,ProxyFactory创建了一个代理对象,并在方法调用之前添加了日志记录功能。
在Java中,代理模式通常用于远程方法调用(RMI)、JDK动态代理或CGLIB代理。在.NET中,可以用Castle DynamicProxy库来创建代理。而在Python中,wrapt库提供了强大的装饰器和代理功能。在C#中,可以使用RealProxy类来实现动态代理。这些技术框架中的代理模式实现方式虽然有所不同,但核心思想都是相同的,即通过代理对象来控制对目标对象的访问。
五、应用场景
代理模式的应用场景非常广泛,包括但不限于以下几个方面:
- 远程代理:为其他对象提供一种代理以控制对这个对象的远程访问。例如,在分布式系统中,客户端可以通过代理对象来访问远程服务器上的对象。
- 虚拟代理:根据需要创建开销很大的对象。在真实对象创建之前,虚拟代理对象可以充当其代理。例如,在加载大型图片或视频时,可以先显示一个占位符或缩略图,待图片或视频加载完成后再显示真实内容。
- 安全代理:控制对资源的访问权限。例如,在Web应用中,可以通过代理对象来检查用户是否具有访问某个资源的权限。
- 智能代理:当调用真实对象时,代理对象可以附加一些额外的处理逻辑。例如,在调用数据库查询方法之前,代理对象可以自动添加分页、排序等处理逻辑。
六、优缺点
优点:
- 中介作用:代理对象可以在客户端和目标对象之间起到中介的作用,从而保护目标对象。
- 功能扩展:代理对象可以扩展目标对象的功能,而不需要修改目标对象的代码。
- 降低耦合度:代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度,增加了程序的可扩展性。
缺点:
- 类数量增加:代理模式会造成系统设计中类的数量增加,从而增加了系统的复杂度。
- 请求处理变慢:在客户端和目标对象之间增加一个代理对象,可能会造成请求处理速度变慢。
综上所述,代理模式是一种非常有用的设计模式,它可以在不修改目标对象代码的前提下,实现对目标对象功能的扩展和保护。同时,代理模式也具有一定的缺点,需要在具体应用场景中进行权衡和选择。

相关文章:
设计模式 结构型 代理模式(Proxy Pattern)与 常见技术框架应用 解析
代理模式(Proxy Pattern)是一种常见的设计模式,在软件开发中有着广泛的应用。其核心思想是通过创建一个代理类来控制对另一个对象的访问,从而实现对目标对象功能的扩展、保护或其他附加操作。 一、核心思想 代理模式的核心思想在…...
Linux环境(CentOs7) 安装 Node环境
Linux环境(CentOs7) 安装 Node环境 使用NodeSource安装Node.js 1、清除缓存(可选但推荐) sudo yum clean all2、添加NodeSource仓库,根据你想要安装的Node.js版本,选择相应的NodeSource安装脚本。例如&am…...
Tailwind CSS 实战:现代登录注册页面开发
在前端开发中,登录注册页面是最常见的需求之一。一个设计精美、交互友好的登录注册页面不仅能提升用户体验,还能增加产品的专业度。本文将详细介绍如何使用 Tailwind CSS 开发一个现代化的登录注册页面。 设计思路 在开始编码之前,我们先明…...
Unity2022接入Google广告与支付SDK、导出工程到Android Studio使用JDK17进行打包完整流程与过程中的相关错误及处理经验总结
注:因为本人也是第一次接入广告与支付SDK相关的操作,网上也查了很多教程,很多也都是只言片语或者缺少一些关键步骤的说明,导致本人也是花了很多时间与精力踩了很多的坑才搞定,发出来也是希望能帮助到其他人在遇到相似问…...
反向传播算法的偏置更新步骤
偏置的更新步骤 假设我们有一个三层神经网络(输入层、隐藏层和输出层),并且每层的激活函数为 sigmoid 函数。我们需要更新隐藏层和输出层的偏置。以下是详细的步骤: 1. 计算误差项(Error Term) 输出层的…...
条款47:请使用 traits classes 表现类型信息(Use traits classes for information about types)
条款47:请使用 traits classes 表现类型信息 1.1 提出问题 想一想,下面的功能如何实现?(可以查看std::advance源码) template<typename IterT, typename DistT> void advance(IterT& iter, DistT d); /…...
yolov5和yolov8的区别
1. yolov5有建议框,yolov8没有建议框 2. yolov5标签中有自信度,而yolov8没有自信度。因为自信度是建议框和真实框的交集 3. yolov5有三个损失函数,回归问题:预测框和建议框的损失(中心点宽高偏移量的损失):CIOUFocal…...
Redis 实现分布式锁
文章目录 引言一、Redis的两种原子操作1.1 Redis 的原子性1.2 单命令1.3 Lua 脚本1.4 对比单命令与 Lua 脚本 二、Redis 实现分布式锁2.1 分布式锁的概念与需求2.1.1 什么是分布式锁?2.1.2 分布式锁的常见应用场景 2.2 基于 Redis 的分布式锁实现2.2.1 锁的获取与释…...
django StreamingHttpResponse fetchEventSource实现前后端流试返回数据并接收数据的完整详细过程
django后端环境介绍: Python 3.10.14 pip install django-cors-headers4.4.0 Django5.0.6 django-cors-headers4.4.0 djangorestframework3.15.2 -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple 总环境如下: Package Version -…...
SpringSpringBoot常用注解总结
目录 1. SpringBootApplication 2. Spring Bean 相关 2.1. Autowired 2.2. Component,Repository,Service, Controller 2.3. RestController 2.4. Scope 2.5. Configuration 3. 处理常见的 HTTP 请求类型 3.1. GET 请求 3.2. POST 请求 3.3. PUT 请求 3.4. DELETE 请…...
24.小R的随机播放顺序<字节青训营-中等题>
1.题目 问题描述 小R有一个特殊的随机播放规则。他首先播放歌单中的第一首歌,播放后将其从歌单中移除。如果歌单中还有歌曲,则会将当前第一首歌移到最后一首。这个过程会一直重复,直到歌单中没有任何歌曲。 例如,给定歌单 [5, …...
【QT】增删改查 XML 文件的类
使用单例类模板实现的对XML文件的节点、属性、文本进行增删改查,可以直接用! 直接POST代码,比较简单好用。 针对以下格式的xml文件比较适用 每个节点的名称都不一样,节点包含了各种属性。 <?xml version="1.0" encoding="UTF-8"?> <config…...
Linux-掉电保护方案
参考链接 https://blog.csdn.net/pwl999/article/details/109411919硬件设计 设备树 驱动程序 #include <linux/module.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/gpio.h>int irq;//中断服务函数 irqreturn_t tes…...
php获取字符串中的汉字
在PHP中,可以使用正则表达式来提取字符串中的汉字。汉字通常位于Unicode范围\u4e00-\u9fa5之内,因此可以使用preg_match_all函数配合适当的正则表达式来实现。 以下是一个PHP代码示例,它会从给定的字符串中提取出所有的汉字: fu…...
java: JDK isn‘t specified for module ‘product-service‘问题解决
目录 问题 解决方法 1.打开File->Project Structure... 2.将Project SDK修改为17 Oracle OpenJDK 17.0.12,并Apply,OK 问题 添加module后报错:java: JDK isnt specified for module product-service 查看pom.xml文件也添加了对应的JDK…...
使用工厂+策略模式实现去除繁琐的if else
使用工厂策略模式实现去除繁琐的if else 在中间有一个mapstruct的bug,即在修改实体类中的类型时,或者修改属性名字,mapstruct都无法进行转换,会报错,此时需要maven cleanmaven compile即可 前言 在这次的开发中&#…...
Dubbo3入门项目搭建
开发环境:jdk8、dubbo3.2.9、nacos2.3.0、springboot2.7.17、dubbo-admin0.6.0。 Dubbo 是一个高性能的 Java RPC(远程调用)框架,最初由阿里巴巴开发并开源,主要用于构建 SOA 架构下的分布式应用系统( soa简单理解就是…...
形象地理解UE4中的数据结构 TLinkedListBase
大家都熟知链表,但不一定能快速看懂UE4中的数据结构。 TLinkedListBase表示“链接”中的一个结点,有三个成员: 一、ElementType Element; 表示具体的业务,例如int链条中的一个整数。 二、NextLink 表示 “下一个Node”&#…...
Python自然语言处理利器:SnowNLP模块深度解析、安装指南与实战案例
Python自然语言处理之SnowNLP模块介绍、安装与常见操作案例 一、SnowNLP模块介绍 SnowNLP是一个专为中文文本设计的Python库,它基于自然语言处理技术,提供了多种功能,包括分词、词性标注、情感分析、文本转换(简繁转换ÿ…...
Llama系列关键知识总结
系列文章目录 第一章:LoRA微调系列笔记 第二章:Llama系列关键知识总结 第三章:LLaVA模型讲解与总结 文章目录 系列文章目录Llama: Open and Efficient Foundation Language Models关键要点LLaMa模型架构:Llama2分组查询注意力 (G…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别
OpenPrompt 和直接对提示词的嵌入向量进行训练有什么区别 直接训练提示词嵌入向量的核心区别 您提到的代码: prompt_embedding = initial_embedding.clone().requires_grad_(True) optimizer = torch.optim.Adam([prompt_embedding...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...
Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...
【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL
ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...
PH热榜 | 2025-06-08
1. Thiings 标语:一套超过1900个免费AI生成的3D图标集合 介绍:Thiings是一个不断扩展的免费AI生成3D图标库,目前已有超过1900个图标。你可以按照主题浏览,生成自己的图标,或者下载整个图标集。所有图标都可以在个人或…...
[拓扑优化] 1.概述
常见的拓扑优化方法有:均匀化法、变密度法、渐进结构优化法、水平集法、移动可变形组件法等。 常见的数值计算方法有:有限元法、有限差分法、边界元法、离散元法、无网格法、扩展有限元法、等几何分析等。 将上述数值计算方法与拓扑优化方法结合&#…...
