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

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

在这里插入图片描述

代理模式(Proxy Pattern)是一种常见的设计模式,在软件开发中有着广泛的应用。其核心思想是通过创建一个代理类来控制对另一个对象的访问,从而实现对目标对象功能的扩展、保护或其他附加操作。

一、核心思想

代理模式的核心思想在于提供一个代理对象,作为客户端与目标对象之间的中介。客户端并不直接调用目标对象的方法,而是通过调用代理对象的方法来间接调用目标对象的方法。这样可以在调用目标对象方法之前或之后添加额外的逻辑,如权限检查、日志记录、事务处理等。

二、定义与结构

定义:代理模式为其他对象提供一种代理以控制对这个对象的访问。

结构

  • 抽象角色(Subject):通过接口或抽象类声明真实角色实现的业务方法。
  • 代理角色(Proxy):实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
  • 真实角色(Real Subject):实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。

角色

在代理模式中,通常涉及以下三个角色:

  • 抽象主题(Subject):定义了真实主题和代理主题的共同接口。
  • 真实主题(Real Subject):实现了具体的业务逻辑,是代理模式中被代理的对象。
  • 代理主题(Proxy Subject):持有对真实主题的引用,可以在调用真实主题之前或之后执行附加的操作。

三、实现步骤及代码示例

以下是通过Java技术框架实现代理模式的详细步骤及代码示例:

静态代理

  1. 定义抽象主题接口:
public interface Subject {void request();
}
  1. 实现真实主题类:
public class RealSubject implements Subject {@Overridepublic void request() {System.out.println("RealSubject: Handling request.");}
}
  1. 实现代理主题类:
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.");}
}
  1. 客户端代码:
public class Client {public static void main(String[] args) {Subject subject = new ProxySubject();subject.request();}
}

动态代理

  1. 定义抽象主题接口(同上)。
  2. 实现真实主题类(同上)。
  3. 创建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.");}
}
  1. 客户端代码:
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类来实现动态代理。这些技术框架中的代理模式实现方式虽然有所不同,但核心思想都是相同的,即通过代理对象来控制对目标对象的访问。

五、应用场景

代理模式的应用场景非常广泛,包括但不限于以下几个方面:

  1. 远程代理:为其他对象提供一种代理以控制对这个对象的远程访问。例如,在分布式系统中,客户端可以通过代理对象来访问远程服务器上的对象。
  2. 虚拟代理:根据需要创建开销很大的对象。在真实对象创建之前,虚拟代理对象可以充当其代理。例如,在加载大型图片或视频时,可以先显示一个占位符或缩略图,待图片或视频加载完成后再显示真实内容。
  3. 安全代理:控制对资源的访问权限。例如,在Web应用中,可以通过代理对象来检查用户是否具有访问某个资源的权限。
  4. 智能代理:当调用真实对象时,代理对象可以附加一些额外的处理逻辑。例如,在调用数据库查询方法之前,代理对象可以自动添加分页、排序等处理逻辑。

六、优缺点

优点

  1. 中介作用:代理对象可以在客户端和目标对象之间起到中介的作用,从而保护目标对象。
  2. 功能扩展:代理对象可以扩展目标对象的功能,而不需要修改目标对象的代码。
  3. 降低耦合度:代理模式能将客户端与目标对象分离,在一定程度上降低了系统的耦合度,增加了程序的可扩展性。

缺点

  1. 类数量增加:代理模式会造成系统设计中类的数量增加,从而增加了系统的复杂度。
  2. 请求处理变慢:在客户端和目标对象之间增加一个代理对象,可能会造成请求处理速度变慢。

综上所述,代理模式是一种非常有用的设计模式,它可以在不修改目标对象代码的前提下,实现对目标对象功能的扩展和保护。同时,代理模式也具有一定的缺点,需要在具体应用场景中进行权衡和选择。

在这里插入图片描述

相关文章:

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

代理模式&#xff08;Proxy Pattern&#xff09;是一种常见的设计模式&#xff0c;在软件开发中有着广泛的应用。其核心思想是通过创建一个代理类来控制对另一个对象的访问&#xff0c;从而实现对目标对象功能的扩展、保护或其他附加操作。 一、核心思想 代理模式的核心思想在…...

Linux环境(CentOs7) 安装 Node环境

Linux环境&#xff08;CentOs7&#xff09; 安装 Node环境 使用NodeSource安装Node.js 1、清除缓存&#xff08;可选但推荐&#xff09; sudo yum clean all2、添加NodeSource仓库&#xff0c;根据你想要安装的Node.js版本&#xff0c;选择相应的NodeSource安装脚本。例如&am…...

Tailwind CSS 实战:现代登录注册页面开发

在前端开发中&#xff0c;登录注册页面是最常见的需求之一。一个设计精美、交互友好的登录注册页面不仅能提升用户体验&#xff0c;还能增加产品的专业度。本文将详细介绍如何使用 Tailwind CSS 开发一个现代化的登录注册页面。 设计思路 在开始编码之前&#xff0c;我们先明…...

Unity2022接入Google广告与支付SDK、导出工程到Android Studio使用JDK17进行打包完整流程与过程中的相关错误及处理经验总结

注&#xff1a;因为本人也是第一次接入广告与支付SDK相关的操作&#xff0c;网上也查了很多教程&#xff0c;很多也都是只言片语或者缺少一些关键步骤的说明&#xff0c;导致本人也是花了很多时间与精力踩了很多的坑才搞定&#xff0c;发出来也是希望能帮助到其他人在遇到相似问…...

反向传播算法的偏置更新步骤

偏置的更新步骤 假设我们有一个三层神经网络&#xff08;输入层、隐藏层和输出层&#xff09;&#xff0c;并且每层的激活函数为 sigmoid 函数。我们需要更新隐藏层和输出层的偏置。以下是详细的步骤&#xff1a; 1. 计算误差项&#xff08;Error Term&#xff09; 输出层的…...

条款47:请使用 traits classes 表现类型信息(Use traits classes for information about types)

条款47&#xff1a;请使用 traits classes 表现类型信息 1.1 提出问题 想一想&#xff0c;下面的功能如何实现&#xff1f;&#xff08;可以查看std::advance源码&#xff09; template<typename IterT, typename DistT> void advance(IterT& iter, DistT d); /…...

yolov5和yolov8的区别

1. yolov5有建议框&#xff0c;yolov8没有建议框 2. yolov5标签中有自信度&#xff0c;而yolov8没有自信度。因为自信度是建议框和真实框的交集 3. yolov5有三个损失函数&#xff0c;回归问题&#xff1a;预测框和建议框的损失(中心点宽高偏移量的损失)&#xff1a;CIOUFocal…...

Redis 实现分布式锁

文章目录 引言一、Redis的两种原子操作1.1 Redis 的原子性1.2 单命令1.3 Lua 脚本1.4 对比单命令与 Lua 脚本 二、Redis 实现分布式锁2.1 分布式锁的概念与需求2.1.1 什么是分布式锁&#xff1f;2.1.2 分布式锁的常见应用场景 2.2 基于 Redis 的分布式锁实现2.2.1 锁的获取与释…...

django StreamingHttpResponse fetchEventSource实现前后端流试返回数据并接收数据的完整详细过程

django后端环境介绍&#xff1a; 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 总环境如下&#xff1a; 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有一个特殊的随机播放规则。他首先播放歌单中的第一首歌&#xff0c;播放后将其从歌单中移除。如果歌单中还有歌曲&#xff0c;则会将当前第一首歌移到最后一首。这个过程会一直重复&#xff0c;直到歌单中没有任何歌曲。 例如&#xff0c;给定歌单 [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中&#xff0c;可以使用正则表达式来提取字符串中的汉字。汉字通常位于Unicode范围\u4e00-\u9fa5之内&#xff0c;因此可以使用preg_match_all函数配合适当的正则表达式来实现。 以下是一个PHP代码示例&#xff0c;它会从给定的字符串中提取出所有的汉字&#xff1a; fu…...

java: JDK isn‘t specified for module ‘product-service‘问题解决

目录 问题 解决方法 1.打开File->Project Structure... 2.将Project SDK修改为17 Oracle OpenJDK 17.0.12&#xff0c;并Apply&#xff0c;OK 问题 添加module后报错&#xff1a;java: JDK isnt specified for module product-service 查看pom.xml文件也添加了对应的JDK…...

使用工厂+策略模式实现去除繁琐的if else

使用工厂策略模式实现去除繁琐的if else 在中间有一个mapstruct的bug&#xff0c;即在修改实体类中的类型时&#xff0c;或者修改属性名字&#xff0c;mapstruct都无法进行转换&#xff0c;会报错&#xff0c;此时需要maven cleanmaven compile即可 前言 在这次的开发中&#…...

Dubbo3入门项目搭建

开发环境&#xff1a;jdk8、dubbo3.2.9、nacos2.3.0、springboot2.7.17、dubbo-admin0.6.0。 Dubbo 是一个高性能的 Java RPC&#xff08;远程调用&#xff09;框架&#xff0c;最初由阿里巴巴开发并开源&#xff0c;主要用于构建 SOA 架构下的分布式应用系统( soa简单理解就是…...

形象地理解UE4中的数据结构 TLinkedListBase

大家都熟知链表&#xff0c;但不一定能快速看懂UE4中的数据结构。 TLinkedListBase表示“链接”中的一个结点&#xff0c;有三个成员&#xff1a; 一、ElementType Element; 表示具体的业务&#xff0c;例如int链条中的一个整数。 二、NextLink 表示 “下一个Node”&#…...

Python自然语言处理利器:SnowNLP模块深度解析、安装指南与实战案例

Python自然语言处理之SnowNLP模块介绍、安装与常见操作案例 一、SnowNLP模块介绍 SnowNLP是一个专为中文文本设计的Python库&#xff0c;它基于自然语言处理技术&#xff0c;提供了多种功能&#xff0c;包括分词、词性标注、情感分析、文本转换&#xff08;简繁转换&#xff…...

Llama系列关键知识总结

系列文章目录 第一章&#xff1a;LoRA微调系列笔记 第二章&#xff1a;Llama系列关键知识总结 第三章&#xff1a;LLaVA模型讲解与总结 文章目录 系列文章目录Llama: Open and Efficient Foundation Language Models关键要点LLaMa模型架构&#xff1a;Llama2分组查询注意力 (G…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎&#xff1a;品融电商&#xff0c;一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中&#xff0c;品牌如何破浪前行&#xff1f;自建团队成本高、效果难控&#xff1b;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

MySQL中【正则表达式】用法

MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现&#xff08;两者等价&#xff09;&#xff0c;用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例&#xff1a; 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配

目录 一、C 内存的基本概念​ 1.1 内存的物理与逻辑结构​ 1.2 C 程序的内存区域划分​ 二、栈内存分配​ 2.1 栈内存的特点​ 2.2 栈内存分配示例​ 三、堆内存分配​ 3.1 new和delete操作符​ 4.2 内存泄漏与悬空指针问题​ 4.3 new和delete的重载​ 四、智能指针…...

【C++进阶篇】智能指针

C内存管理终极指南&#xff1a;智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...