设计模式 结构型 代理模式(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…...
自制射频功率计:基于AD8317芯片,成本43欧元实现1MHz-10GHz测量
1. 项目概述:为什么我要亲手打造一台射频功率计在无人机和模型飞行器的圈子里,尤其是在我们荷兰FMS Spaarnwoude俱乐部,合规飞行是头等大事。我给我的八轴飞行器加装了云台相机和图传系统,工作在5.8GHz频段。根据本地法规…...
Unity事件系统实战:用事件驱动重构你的金币拾取逻辑(告别硬编码)
Unity事件系统实战:用事件驱动重构你的金币拾取逻辑(告别硬编码)在游戏开发中,我们经常会遇到这样的场景:玩家拾取金币后,需要更新UI、播放音效、解锁成就、保存数据……如果把这些逻辑全部写在金币拾取的代…...
InVideo插件深度解析:如何在Unreal Engine中实现高效视频流播放与录制
InVideo插件深度解析:如何在Unreal Engine中实现高效视频流播放与录制 【免费下载链接】InVideo 基于UE4实现的rtsp的视频播放插件 项目地址: https://gitcode.com/gh_mirrors/in/InVideo InVideo是一个基于Unreal Engine 5开发的RTSP视频播放插件࿰…...
数字合成器d-FORMANT:从模拟经典到数字复刻的工程实践
1. 项目概述:从模拟经典到数字复刻如果你对合成器稍有了解,或者对电子音乐制作背后的硬件感兴趣,那么“FORMANT”这个名字你一定不陌生。它最初是上世纪70年代由《Elektor》杂志发布的一款模拟单音合成器,以其清晰的模块化设计和出…...
基于BLE模块的低功耗无线遥控器设计与实现
1. 项目概述:基于BLE模块的无线遥控器设计与实现几年前,我在捣鼓智能家居时,一直想找一个低功耗、响应快、又能自己完全掌控的无线遥控方案。市面上的成品要么协议封闭,要么功耗感人,要么延迟高得让人着急。后来&#…...
LLM测试工程师必看,Claude E2E测试架构设计,从用例生成、黄金样本构建到回归基线告警闭环
更多请点击: https://codechina.net 第一章:LLM测试工程师必看,Claude E2E测试架构设计,从用例生成、黄金样本构建到回归基线告警闭环 核心架构概览 Claude端到端测试架构采用三层解耦设计:输入层(动态用…...
Windows 11终极优化指南:一键清理系统,释放51%性能潜力
Windows 11终极优化指南:一键清理系统,释放51%性能潜力 【免费下载链接】Win11Debloat A simple, lightweight PowerShell script that allows you to remove pre-installed apps, disable telemetry, as well as perform various other changes to decl…...
Unity动态植被系统:实时天气与自然现象耦合方案
1. 这不是“贴图堆砌”,而是一套可交互的自然系统你有没有试过在Unity里拖进几棵树、铺点草地,结果运行起来——风一吹,所有树叶像被钉在空中一样纹丝不动;下雨时,雨滴垂直砸进地面,连个水花都没有…...
ABS+神经网络:端到端宇宙学参数推断新范式解析
1. 项目概述:当ABS遇上神经网络,一个端到端宇宙学参数推断新范式的诞生 在宇宙学研究的核心地带,有一项任务既令人着迷又充满挑战:如何从宇宙微波背景(CMB)这张宇宙婴儿时期的“照片”中,精准地…...
Arduino打地鼠游戏机:从74HC595矩阵驱动到状态机编程全解析
1. 项目概述:用Arduino复刻经典打地鼠游戏作为一个电子爱好者,我总想把手头的Arduino和各种元器件玩出点新花样。这次,我决定挑战一个经典街机项目——电子打地鼠。市面上虽然有现成的玩具,但自己从头设计、画板、编程,…...
