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

GPT带我学-设计模式-代理模式

什么是代理模式

代理模式(Proxy Pattern)是设计模式中的一种结构型模式,它为其他对象提供一种代理以控制对这个对象的访问。

代理模式有三个主要角色:抽象主题(Subject)、真实主题(Real Subject)和代理(Proxy)。

抽象主题(Subject):定义了真实主题与代理之间的共同接口,这样真实主题和代理可以互相替换使用。

真实主题(Real Subject):指实际要被代理的对象。

代理(Proxy):提供了一个与真实主题相同的接口,它内部持有一个真实主题的引用,并在真实主题的实例化或执行某些操作前后进行控制或扩展。

代理模式的主要目的是在不改变真实主题的情况下,为其提供一个代理类来进行访问控制或增强功能。代理模式可以实现懒加载,即在真正需要使用真实主题的时候才进行实例化,从而节省资源和提高性能。代理模式还能提供额外的功能,例如在调用真实主题的方法前后进行日志记录、安全控制、事务管理等。

代理模式可以分为静态代理和动态代理。静态代理是通过手动编写代理类来实现的,而动态代理则是在运行时动态生成代理类。动态代理通常使用Java的反射机制来实现,可以减少冗余代码,并且对真实主题的访问完全透明。

总之,代理模式提供了一种间接访问对象的方式,可以控制对象的访问、增强对象的功能,并且可以在不改变真实对象的情况下进行扩展。

代理模式有几种形式

在设计模式中,代理模式有两种常见的形式:

静态代理(Static Proxy):静态代理需要手动编写代理类,代理类和真实主题类实现相同的接口或继承相同的父类,并在代理类中持有一个真实主题类的引用。静态代理在编译时就确定了代理对象和真实对象的关系。

动态代理(Dynamic Proxy):动态代理在运行时动态生成代理类,不需要手动编写代理类。Java中的动态代理通常使用Java反射机制实现,可以通过Proxy类和InvocationHandler接口来创建动态代理对象。动态代理可以代理接口或类,适用于需要代理多个不同类型对象的场景。

在静态代理和动态代理中,代理类都是通过调用真实主题类的方法,并在方法前后加上一些额外的逻辑(如日志记录、权限验证等)来控制或增强真实主题的功能。

除了静态代理和动态代理,还有一些其他的代理变体形式,如远程代理、虚拟代理、保护代理等,这些形式根据具体的应用场景和需求进行使用。

请举一个具体的静态代理例子

假设有一个接口 Subject,定义了一个抽象主题的操作方法 request()。现在我们需要用静态代理来实现在真实主题的执行前后进行日志记录。

首先,定义一个 Subject 接口:

public interface Subject {void request();
}

接下来,创建真实主题类 RealSubject,实现 Subject 接口:

public class RealSubject implements Subject {@Overridepublic void request() {System.out.println("真实主题执行请求");}
}

然后,创建一个代理类 ProxySubject,实现 Subject 接口,并在 request() 方法的前后添加日志记录的逻辑:

public class ProxySubject implements Subject {private RealSubject realSubject;public ProxySubject(RealSubject realSubject) {this.realSubject = realSubject;}@Overridepublic void request() {System.out.println("代理主题执行请求之前的日志记录");// 调用真实主题的方法realSubject.request();System.out.println("代理主题执行请求之后的日志记录");}
}

最后,我们可以通过以下代码来使用静态代理:

public class Main {public static void main(String[] args) {RealSubject realSubject = new RealSubject();ProxySubject proxy = new ProxySubject(realSubject);proxy.request();}
}

运行程序,输出结果如下:

代理主题执行请求之前的日志记录
真实主题执行请求
代理主题执行请求之后的日志记录

可以看到,通过静态代理模式,我们在真实主题的执行前后添加了日志记录的逻辑,实现了对真实主题的控制和功能增强,而不需要修改真实主题类的代码。这是静态代理模式的一种常见应用场景。

同样的例子怎么改成动态代理模式呢

要将上述示例改为动态代理模式,需使用Java的动态代理实现。首先,需要借助 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口。

首先,定义 Subject 接口和 RealSubject 真实主题类,与上述示例相同。

接下来,创建一个实现 InvocationHandler 接口的代理处理器类 ProxyHandler,用于在真实主题的方法执行前后添加日志记录的逻辑。在 invoke() 方法中,可以定义增强的逻辑以及调用真实主题的方法。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;public class ProxyHandler implements InvocationHandler {private Object realSubject;public ProxyHandler(Object realSubject) {this.realSubject = realSubject;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("代理主题执行请求之前的日志记录");// 调用真实主题的方法Object result = method.invoke(realSubject, args);System.out.println("代理主题执行请求之后的日志记录");return result;}
}

最后,可以通过以下代码来使用动态代理:

import java.lang.reflect.Proxy;public class Main {public static void main(String[] args) {RealSubject realSubject = new RealSubject();InvocationHandler handler = new ProxyHandler(realSubject);// 创建动态代理对象Subject proxySubject = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(),realSubject.getClass().getInterfaces(),handler);proxySubject.request();}
}

运行程序,输出结果与静态代理的例子相同:

代理主题执行请求之前的日志记录
真实主题执行请求
代理主题执行请求之后的日志记录

可以看到,通过动态代理模式,我们实现了在真实主题的执行前后添加日志记录的逻辑,而不需要直接操作代理类,使代理对象动态生成,并且能够透明地调用真实主题的方法。这是动态代理模式的一种常见应用场景。

补充说明(《Head First设计模式》)

java在java.lang.reflect包中有自己的代理实现方式,通过相关api可以动态创建一个代理类。
通过代理类去调用被代理的方法。
因为实际代理类是在运行时创建的,所以把java的这个技术叫做动态代理。
Java为我们动态创建了Proxy。我们通过实现InvocationHandler接口告诉Proxy去做什么。

相关文章:

GPT带我学-设计模式-代理模式

什么是代理模式 代理模式(Proxy Pattern)是设计模式中的一种结构型模式,它为其他对象提供一种代理以控制对这个对象的访问。 代理模式有三个主要角色:抽象主题(Subject)、真实主题(Real Subje…...

VMware Workstation Pro 无法使用开机状态下拍的快照来克隆虚拟机,怎么解决?

环境: VMware Workstation Pro16.0 Win10 专业版 问题描述: VMware Workstation Pro有台虚拟机在开机状态下拍了个6.7快照这个win10初始版,现在想在这个快照下直接克隆,无法使用开机状态下拍的快照创建克隆 解决方案: 1.关闭当前虚拟机 2.到虚拟机文件夹复制一份Wind…...

【JAVA】XML及其解析技术、XML检索技术、设计模式

XML XML(Extensible Markup Language)是可扩展标记语言的缩写&#xff0c;它是一种数据表示格式&#xff0c;可以描述复杂的数据结构&#xff0c;常用于传输和存储数据 作用&#xff1a; 用于进行存储数据和传输数据作为软件的配置文件 第一行是文档声明 <?xml version&q…...

Ansible 自动化安装软件

例子如下&#xff1a; 创建一个名为/ansible/package.yml 的 playbook : 将 php 和 mariadb 软件包安装到 dev、test 和 prod 主机组中的主机上 将 RPM Development Tools 软件包组安装到 dev 主机组中的主机上 将 dev 主机组中主机上的所有软件包更新为最新版本 --- - name:…...

简单介绍 React Native 整合 Formik 实现表单校验

Formik 是 React 和 React Native 开源表单库&#xff0c;Formik 负责处理重复且烦人的事情——跟踪值/错误/访问的字段、编排验证和处理提交——所以您不必这样做。而简化字段校验的话我们可以使用yup工具来实现。 首先安装Formik 和 Yup npm i formik npm i yupFormik 与 R…...

蓝帽杯半决赛2022

手机取证_1 iPhone手机的iBoot固件版本号:&#xff08;答案参考格式&#xff1a;iBoot-1.1.1&#xff09; 直接通过盘古石取证 打开 取证大师和火眼不知道为什么都无法提取这个 手机取证_2 该手机制作完备份UTC8的时间&#xff08;非提取时间&#xff09;:&#xff08;答案…...

电路学习+硬件每日学习十个知识点(40)23.8.20 (希腊字母读音,阶跃信号和冲激信号的关系式,信号的波形变换,信号的基本运算,卷积积分,卷积和)

文章目录 1.信号具有时间特性和频率特性。2.模拟转数字&#xff0c;抽样、量化、编码3.阶跃信号和冲激信号4.信号的波形变换&#xff08;时移、折叠、尺度变换&#xff09;5.信号的基本运算&#xff08;加减、相乘、微分与积分、差分与累加&#xff09;5.1 相加减5.2 相乘5.3 微…...

Python——列表(list)推导式

本文基于python3。 目录 1、Python推导式2、列表(list)推导式2.1、定义2.2、实际操作2.2.1、一个表达式&#xff0c;后面为一个 for 子句2.2.2、一个表达式&#xff0c;后面为一个 for 子句&#xff0c;然后&#xff0c;跟着if 子句。2.2.3、一个表达式&#xff0c;后面为一个…...

代码随想录算法训练营day43 | LeetCode 1049. 最后一块石头的重量 II 494. 目标和 474. 一和零

1049. 最后一块石头的重量 II&#xff08;题目链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台&#xff09; 思路&#xff1a;把全部石头重量加起来&#xff0c;然后除以二&#xff0c;就等于背包的最大容量。然后就可以按照背包问题…...

Linux安装jdk、mysql、并部署Springboot项目

&#x1f61c;作 者&#xff1a;是江迪呀✒️本文关键词&#xff1a;Linux、环境安装、JDK安装、MySQL、MySQL安装☀️每日 一言&#xff1a;知行合一&#xff01; 文章目录 一、前言二、安装步骤2.1 安装JDK&#xff08;1&#xff09;创建文件夹&#xff08;便于后…...

tomcat更改端口号和隐藏端口号

因为默认端口:8080不会自动隐藏&#xff0c;因此为了更显格调需要将其改为:80 进入tomcat的server文件 将其改为80&#xff0c;之后将tomcat重新启动即可 tomcat启动流程 [rootshang ~]# cd /usr/local/tomcat/apache-tomcat-8.5.92 [rootshang apache-tomcat-8.5.92]# cd b…...

生信分析Python实战练习 2 | 视频19

开源生信 Python教程 生信专用简明 Python 文字和视频教程 源码在&#xff1a;https://github.com/Tong-Chen/Bioinfo_course_python 目录 背景介绍 编程开篇为什么学习Python如何安装Python如何运行Python命令和脚本使用什么编辑器写Python脚本Python程序事例Python基本语法 数…...

wps设置其中几页为横版

问题&#xff1a;写文档的时候&#xff0c;有些表格列数太多&#xff0c;页面纵向显示内容不完整&#xff0c;可以给它改成横向显示。 将鼠标放在表格上一页的底部&#xff0c;点击‘插入-分页-下一页分节符’。 将鼠标放在表格页面的底部&#xff0c;点击‘插入-分页-下一页分…...

如何在Ubuntu 22.04上安装PHP 8.1并设置本地开发环境

引言 PHP是一种流行的服务器脚本语言&#xff0c;用于创建动态和交互式web页面。开始使用你选择的语言是学习编程的第一步。 本教程将指导您在Ubuntu上安装PHP 8.1&#xff0c;并通过命令行设置本地编程环境。您还将安装依赖管理器Composer&#xff0c;并通过运行脚本来测试您…...

wazuh安装与使用

目录 一、wazuh安装 二、wazuh使用 一、wazuh安装 下载&#xff1a;https://wazuh.com 可以直接安装OVA这个&#xff0c;然后导入到Linux中就可以使用了。 导入完毕后开启&#xff0c;使用远程连接工具进行连接&#xff0c;出现以下画面则成功了。 之后可以看一下图形化界面…...

Vue 3 常见面试题汇总

前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 前言 最近两年许多大厂都在实行“降本增效”、“优化组织架构”&#xff0c;然后“为社会输送了大量人才”&#xff0c;今年&#xff08;2023&#xff…...

Docker是什么?详谈它的框架、使用场景、优势

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 作者会持续更新网络知识和python基础知识&#xff0c;期待你的关注 目录 一、什么是 Docker&#xff1f; 二、Docker 的架构 1、Docker客户端 2、Docker守护进程 3、Docker镜像 4、Docker容器 5、Docker…...

neo4j

UNWIND 将列表里的值展开 CREATE (N0:Person {name: Anders}) CREATE (N1:Person {name: Becky}) CREATE (N2:Person {name: Cesar}) CREATE (N3:Person {name: Dilshad}) CREATE (N4:Person {name: George}) CREATE (N5:Person {name: Filipa})CREATE (N0)-[:KNOWS]->(N3)…...

【项目 计网5】 4.15 TCP通信实现(服务器端)4.16 TCP通信实现(客户端)

文章目录 4.15 TCP通信实现&#xff08;服务器端&#xff09;4.16 TCP通信实现&#xff08;客户端&#xff09; 4.15 TCP通信实现&#xff08;服务器端&#xff09; // TCP 通信的服务器端// TCP 通信的服务器端 #include <stdio.h> #include <arpa/inet.h> #incl…...

windows可视化界面管理服务器上的env文件

需求&#xff1a;在 Windows 环境中通过可视化界面编辑位于 Linux 主机上的 env 文件的情况&#xff0c;我现在环境是windows环境&#xff0c;我的env文件在linux的192.168.20.124上&#xff0c;用户是op&#xff0c;密码是op&#xff0c;文件绝对路径是/home/op/compose/env …...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

【网络安全产品大调研系列】2. 体验漏洞扫描

前言 2023 年漏洞扫描服务市场规模预计为 3.06&#xff08;十亿美元&#xff09;。漏洞扫描服务市场行业预计将从 2024 年的 3.48&#xff08;十亿美元&#xff09;增长到 2032 年的 9.54&#xff08;十亿美元&#xff09;。预测期内漏洞扫描服务市场 CAGR&#xff08;增长率&…...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

el-switch文字内置

el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南

精益数据分析&#xff08;97/126&#xff09;&#xff1a;邮件营销与用户参与度的关键指标优化指南 在数字化营销时代&#xff0c;邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天&#xff0c;我们将深入解析邮件打开率、网站可用性、页面参与时…...