代理模式的理解和实践

        代理模式(Proxy Pattern)是一种结构型设计模式,它允许你为其他对象提供一种代理以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介的作用,客户端通过代理对象间接地访问目标对象。通过这种方式,代理模式可以在不修改目标对象的前提下,为目标对象添加额外的功能或控制访问权限。

        本文将详细介绍代理模式的概念、种类、优缺点,并通过Java代码示例展示如何在实践中应用代理模式。

 

一、代理模式的概念

  1. 定义:代理模式为其他对象提供一种代理,以控制对这个对象的访问。代理对象在客户端和目标对象之间起到中介的作用,客户端通过代理对象间接地访问目标对象。

  2. 结构

    • Subject:抽象主题角色,声明了代理和真实对象的共同接口。
    • RealSubject:真实主题角色,实现了抽象主题接口,是代理对象所代表的真实对象。
    • Proxy:代理角色,持有一个真实对象的引用,可以控制对真实对象的访问,也可以附加额外的功能。
  3. 种类

    • 静态代理:代理类在编译时就确定下来,代理类和目标类的关系在运行前就已经确定,且不可改变。
    • 动态代理:代理类在运行时由JVM根据反射机制动态生成,代理类和目标类的关系在运行时确定。

二、静态代理的理解和实践

        静态代理通过定义一个代理类,并在代理类中调用目标对象的方法来实现。这种方式需要在编译时就确定代理类。

示例代码

定义抽象主题接口

// 抽象主题接口
public interface Image {void display();
}


实现真实主题类

// 真实主题类
public class RealImage implements Image {private String filename;public RealImage(String filename) {this.filename = filename;loadFromDisk(filename);}private void loadFromDisk(String filename) {System.out.println("Loading " + filename);}@Overridepublic void display() {System.out.println("Displaying " + filename);}
}

定义代理类

// 代理类
public class ProxyImage implements Image {private RealImage realImage;private String filename;public ProxyImage(String filename) {this.filename = filename;}@Overridepublic void display() {if (realImage == null) {realImage = new RealImage(filename);}realImage.display();}
}

客户端代码

public class Client {public static void main(String[] args) {Image image = new ProxyImage("test.jpg");// 图像将从磁盘加载并显示image.display();}
}


        在这个示例中,ProxyImage 是 RealImage 的代理类,它持有一个 RealImage 的引用,并在需要时才加载真实的图像对象。通过这种方式,可以在不修改 RealImage 的前提下,为其添加懒加载功能。

三、动态代理的理解和实践

        动态代理通过Java反射机制在运行时动态生成代理类,而不需要在编译时确定代理类。Java提供了 java.lang.reflect.Proxy 类和 java.lang.reflect.InvocationHandler 接口来实现动态代理。

示例代码

定义抽象主题接口

// 抽象主题接口
public interface Image {void display();
}

实现真实主题类

// 真实主题类
public class RealImage implements Image {private String filename;public RealImage(String filename) {this.filename = filename;loadFromDisk(filename);}private void loadFromDisk(String filename) {System.out.println("Loading " + filename);}@Overridepublic void display() {System.out.println("Displaying " + filename);}
}

定义动态代理处理器

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;// 动态代理处理器
public class ImageInvocationHandler implements InvocationHandler {private Object realObject;public ImageInvocationHandler(Object realObject) {this.realObject = realObject;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if ("display".equals(method.getName())) {System.out.println("Proxy: Loading image proxy...");Object result = method.invoke(realObject, args);return result;}return null;}
}

客户端代码

import java.lang.reflect.Proxy;public class Client {public static void main(String[] args) {Image realImage = new RealImage("test.jpg");Image proxyInstance = (Image) Proxy.newProxyInstance(realImage.getClass().getClassLoader(),realImage.getClass().getInterfaces(),new ImageInvocationHandler(realImage));// 图像将通过代理加载并显示proxyInstance.display();}
}


        在这个示例中,ImageInvocationHandler 是动态代理处理器,它实现了 InvocationHandler 接口。Proxy.newProxyInstance 方法在运行时动态生成代理类,并返回一个实现了 Image 接口的代理对象。客户端通过代理对象调用 display 方法时,会触发 ImageInvocationHandler 的 invoke 方法,从而实现对真实对象的访问控制。

四、代理模式的优缺点

优点

  1. 增强功能:代理模式可以在不修改目标对象的前提下,为目标对象添加额外的功能。
  2. 控制访问:代理模式可以控制对目标对象的访问权限,例如限制访问次数或时间。
  3. 缓存和懒加载:代理模式可以实现缓存和懒加载机制,提高系统的性能和资源利用率。

缺点

  1. 复杂性:代理模式增加了系统的复杂性,特别是当代理类较多时,代码会变得难以维护。
  2. 性能开销:代理模式在客户端和目标对象之间增加了一层中介,可能会引入额外的性能开销。

总结

        代理模式是一种结构型设计模式,它允许你为其他对象提供一种代理以控制对这个对象的访问。代理模式可以在不修改目标对象的前提下,为目标对象添加额外的功能或控制访问权限。静态代理和动态代理是代理模式的两种实现方式,静态代理在编译时确定代理类,而动态代理在运行时动态生成代理类。通过Java代码示例,我们可以更好地理解和实践代理模式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/889135.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

3维建模blender

官网稳定版下载:https://www.blender.org/download/lts/ windows有安装版和portable版 教程:https://www.bilibili.com/video/BV1kX4y1m7G5 1. 基础操作 场景操作 场景位移:shift鼠标中键长按场景旋转:鼠标中键长按场景缩放&…

Autoformer: 一种基于自动相关机制的时序预测新架构

论文题目: Autoformer:Decomposition Transformers with Auto-Correlation for Long-Term Series Forecasting 论文地址:https://openreview.net/pdf?idI55UqU-M11y 今天给大家介绍一篇时序预测领域的重要算法——Autoformer,由李华等人于2020年提出&am…

2024-12月js逆向案例-sensor-data之vmp字段之akamai_2/3.0-(下)

目录 一、初始插桩二、长串的由来三、短串的由来2024-12月akamai_2.0-sensor-data之cookie反爬分析详细教程(上)2024-12月akamai_2.0-sensor-data之cookie反爬分析详细教程(中)一、初始插桩 1、其实就是研究dFT的由来,解混淆得到如下**var dFT = ‘’‘concat’‘concat’…

GAMES101:现代计算机图形学-笔记-10

今天来聊一些基本的概念:相机,棱镜与光场。 众所周知,成像的方法有两种:合成与捕获。 像我们之前所学的内容如光栅化,如光线追踪,本质上都是合成图像的方法,他们只是在计算机中模拟来成像。 那…

深信服ATRUST与锐捷交换机端口链路聚合的配置

深信服ATRUST业务口原来只配置使用一个电口,近期出现流量达到800-900M接近端口的极限带宽。由于设备没有万光口,于是只好用2个光口来配置链接聚合。 下需附上深信服ATRST端口配置的截图,由于深信服ATRUST与锐捷交换机端口只共同支持源mac目的…

华为HarmonyOS NEXT 原生应用开发:页面路由、页面和组件生命周期函数

页面路由、组件生命周期 一、路由的基本使用 1. 如何新建页面 直接右键新建Page。【这个是最直接最常用的】新建普通ets文件,然后通过配置变成页面。 【该方法是遇到这种情况的解决方案】 2. 路由 - 页面之间的跳转 使用 **router.pushUrl({}&#xff…

Vulhub:Log4j[漏洞复现]

CVE-2017-5645(Log4j反序列化) 启动靶场环境 docker-compose up -d 靶机IPV4地址 ifconfig | grep eth0 -A 5 ┌──(root㉿kali)-[/home/kali/Desktop/temp] └─# ifconfig | grep eth0 -A 5 eth0: flags4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 in…

电子商务人工智能指南 4/6 - 内容理解

介绍 81% 的零售业高管表示&#xff0c; AI 至少在其组织中发挥了中等至完全的作用。然而&#xff0c;78% 的受访零售业高管表示&#xff0c;很难跟上不断发展的 AI 格局。 近年来&#xff0c;电子商务团队加快了适应新客户偏好和创造卓越数字购物体验的需求。采用 AI 不再是一…

`yarn list --pattern element-ui` 是一个 Yarn 命令,用于列出项目中符合指定模式(`element-ui`)的依赖包信息

文章目录 命令解析&#xff1a;功能说明&#xff1a;示例输出&#xff1a;使用场景&#xff1a; yarn list --pattern element-ui 是一个 Yarn 命令&#xff0c;用于列出项目中符合指定模式&#xff08; element-ui&#xff09;的依赖包信息。 命令解析&#xff1a; yarn list…

播放器秒开优化

开篇 先说结论&#xff1a; 字节跳动就曾给出过一份数据&#xff1a;对一部分型号的 Android 手机&#xff0c;播放首帧时长从平均 170ms 优化到 100ms&#xff0c;带来了 0.6% 左右的用户播放时长提升。 衡量指标&#xff1a; 播放秒开率&#xff0c;指的是播放器开始初始…

【sgAudioDialog】自定义组件:基于audio标签和el-dialog构建弹窗预览音频文件

sgAudioDialog源码 <template><div :class"$options.name" v-if"visible"><!-- 如果不加v-if"visible"弹窗中使用el-tabs组件就会死循环卡死&#xff0c;这个是elementUI的bug --><el-dialog:append-to-body"true&qu…

docker nginx 部署vue 实例

1.安装docker https://blog.csdn.net/apgk1/article/details/144354588 2. 安装nginx docker 安装 nginx-CSDN博客 3. 复制 nginx-test 实例的一些文件到宿主机中&#xff0c;目前已 /home/jznh/路径演示 3.1 在/home/jznh/ 创建 conf html logs 三个文件夹&#xff0c;…

技术人员需要成为的八边形战士

那天偶然看到一个标题&#xff1a;脾气好&#xff0c;技术佳&#xff0c;哪个程序员这么宝藏&#xff1f;我没有点进去看内容&#xff0c;但是心里在琢磨一件事&#xff1a;10年前这种宝藏程序员很难得&#xff0c;现在的市场&#xff0c;恐怕不够。恐怕市场在找的都是下面技能…

VAS1260Q奇力LED驱动芯片DCDC降压恒流可替代Diodes8860

VAS1260Q是一款专为车规级LED照明设计的连续模式电感降压驱动器&#xff0c;能够高效地驱动单个或多个串联LED。它集成了高端输出电流检测电路&#xff0c;并通过外部电阻设置标称平均输出电流&#xff0c;具有高可靠性和宽广的应用场景。 核心技术参数 1. 输入电压范围…

VLDB 2024 | 时空数据(Spatial-temporal)论文总结

VLDB 2024于2024年8月26号-8月30号在中国广州举行。 本文总结了VLDB 2024有关时空数据&#xff08;time series data&#xff09;的相关论文&#xff0c;主要包含如有疏漏&#xff0c;欢迎大家补充。 &#x1f31f;【紧跟前沿】“时空探索之旅”与你一起探索时空奥秘&#xf…

【推荐算法】单目标精排模型——FiBiNET

key word: 学术论文 Motivation&#xff1a; 传统的Embedding&MLP算法是通过内积和Hadamard product实现特征交互的&#xff0c;这篇文章的作者提出了采用SENET实现动态学习特征的重要性&#xff1b;作者认为简单的内积和Hadamard product无法有效对稀疏特征进行特征交互&a…

Windows中将springboot项目运行到docker的容器中

0&#xff0c;先打包好项目&#xff0c;再启动docker 1&#xff0c;在Java项目根目录下创建一个名为Dockerfile的文件&#xff08;没有扩展名&#xff09;&#xff0c;并添加以下内容。 # 使用OpenJDK的基础镜像 FROM openjdk:8-jdk-alpine# 设置工作目录 WORKDIR /app# 将项…

GB28181系列一:GB28181协议介绍

我的音视频/流媒体开源项目(github) GB28181系列目录 目录 一、GB28181协议介绍 二、GB28181交互流程 1、注册 2、观看视频 3、控制 4、SDP 5、媒体保活&#xff1a; 6、RTP 7、SIP URL 一、GB28181协议介绍 GB28181使用SIP协议&#xff0c;SIP协议参考我的SIP系列&a…

【C++指南】类和对象(七):友元

&#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《C指南》 期待您的关注 目录 引言 &#x1f343;友元的介绍 &#x1f343;友元函数 &#x1f343;友元类 &#x1f343;相关…

使用requests和BeautifulSoup的Python爬虫示例

标题“使用requests和BeautifulSoup的Python爬虫示例”清晰地指出了这个Python脚本的主要功能和所使用的库。以下是一个基于这个标题的Python爬虫代码示例&#xff0c;它展示了如何使用requests库发送HTTP请求&#xff0c;并使用BeautifulSoup库解析HTML内容来抓取网页上的特定…