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

十二、结构型(代理模式)

代理模式(Proxy Pattern)

概念
代理模式(Proxy Pattern)是一种结构型设计模式,代理对象在不改变目标对象功能的前提下,通过控制对目标对象的访问,来实现延迟加载、权限控制、日志记录等功能。代理模式可以通过提供一个中介对象,来控制客户端和实际目标对象之间的交互。


应用场景

  1. 远程代理(Remote Proxy):为位于不同地址空间的对象提供代理,解决远程调用问题。典型的例子是RMI(Remote Method Invocation),通过代理对象进行远程方法调用。

  2. 虚拟代理(Virtual Proxy):为某些需要较高开销的对象提供代理,延迟其加载和创建。比如,大型图片或文档的加载可以通过虚拟代理来进行,只有当真正需要时才创建实际对象。

  3. 保护代理(Protection Proxy):用于控制对对象的访问权限。代理对象检查调用者是否具有访问权限,只有在权限允许时,才能访问目标对象。

  4. 智能引用代理(Smart Reference Proxy):在访问对象时加入一些附加操作,如统计实际对象的引用次数、记录日志、检查锁等。

  5. 缓存代理(Caching Proxy):代理可以缓存某些计算结果或操作结果,使得后续的相同请求不需要重复计算,提升系统性能。


注意点

  • 代理类和实际类必须实现相同的接口:代理类的设计应与目标类保持一致,使得客户端在使用代理类时与使用实际类没有差异。
  • 性能开销:尽管代理模式可以增加功能,但也可能增加系统开销,尤其是远程代理涉及到网络传输时。
  • 适合复杂的控制场景:代理模式尤其适合在需要控制访问、管理复杂操作、或添加额外处理逻辑的场景中使用。

核心要素

  1. Subject(抽象主题角色):定义代理类和目标类的共同接口,使得代理类和目标类可以被客户端通过相同的方式调用。
  2. RealSubject(真实主题角色):定义目标对象,实现真实的业务逻辑。
  3. Proxy(代理角色):负责控制对真实主题对象的访问,通常会引用一个真实主题对象,并通过实现抽象主题接口来代理其操作。

Java代码完整示例

代码示例:静态代理

// 抽象接口,定义真实主题和代理共同的行为
interface Subject {void request();
}// 真实主题,实现实际的业务逻辑
class RealSubject implements Subject {@Overridepublic void request() {System.out.println("真实主题执行请求");}
}// 代理类,控制对真实主题的访问
class Proxy implements Subject {private RealSubject realSubject;@Overridepublic void request() {// 代理可以在调用真实对象之前执行一些额外操作if (realSubject == null) {realSubject = new RealSubject();}System.out.println("代理:在调用真实对象前的额外操作");realSubject.request();System.out.println("代理:在调用真实对象后的额外操作");}
}// 客户端
public class Client {public static void main(String[] args) {Subject proxy = new Proxy();proxy.request();}
}

输出结果

代理:在调用真实对象前的额外操作
真实主题执行请求
代理:在调用真实对象后的额外操作

各种变形用法完整示例

  1. 虚拟代理(Virtual Proxy)
    虚拟代理的主要目的是推迟大开销对象的创建,直到需要使用时才创建。典型例子是延迟加载大型图片或文档。

    代码示例

    interface Image {void display();
    }// 真实的图像类,实际加载图片
    class RealImage implements Image {private String fileName;public RealImage(String fileName) {this.fileName = fileName;loadFromDisk();}private void loadFromDisk() {System.out.println("加载图片: " + fileName);}@Overridepublic void display() {System.out.println("显示图片: " + fileName);}
    }// 虚拟代理类
    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 VirtualProxyClient {public static void main(String[] args) {Image image = new ProxyImage("test.jpg");// 图片首次显示时加载image.display();System.out.println("");// 第二次调用时不需要加载image.display();}
    }
    

    输出结果

    加载图片: test.jpg
    显示图片: test.jpg显示图片: test.jpg
    
  2. 动态代理(Dynamic Proxy)
    动态代理是在运行时创建代理类,而不是在编译时创建。在Java中,可以使用java.lang.reflect.Proxy类来实现动态代理,代理类可以动态代理接口定义的所有方法。

    代码示例

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;// 定义抽象接口
    interface Service {void operation();
    }// 实现接口的真实类
    class RealService implements Service {@Overridepublic void operation() {System.out.println("执行实际操作");}
    }// 动态代理处理器
    class DynamicProxyHandler implements InvocationHandler {private Object target;public DynamicProxyHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("动态代理:在方法执行前");Object result = method.invoke(target, args);System.out.println("动态代理:在方法执行后");return result;}
    }// 客户端
    public class DynamicProxyClient {public static void main(String[] args) {RealService realService = new RealService();Service proxyInstance = (Service) Proxy.newProxyInstance(realService.getClass().getClassLoader(),realService.getClass().getInterfaces(),new DynamicProxyHandler(realService));proxyInstance.operation();}
    }
    

    输出结果

    动态代理:在方法执行前
    执行实际操作
    动态代理:在方法执行后
    
  3. 保护代理(Protection Proxy)
    保护代理用于控制访问权限,可以通过代理来检查调用者是否具备权限,只有在通过检查时,才能调用目标对象的方法。

    代码示例

    interface BankAccount {void deposit(double amount);void withdraw(double amount);
    }class RealBankAccount implements BankAccount {private double balance;public RealBankAccount(double balance) {this.balance = balance;}@Overridepublic void deposit(double amount) {balance += amount;System.out.println("存款成功,当前余额: " + balance);}@Overridepublic void withdraw(double amount) {if (balance >= amount) {balance -= amount;System.out.println("取款成功,当前余额: " + balance);} else {System.out.println("余额不足,取款失败");}}
    }// 保护代理类
    class ProtectionProxy implements BankAccount {private RealBankAccount realBankAccount;private String userRole;public ProtectionProxy(String userRole, double initialBalance) {this.userRole = userRole;realBankAccount = new RealBankAccount(initialBalance);}@Overridepublic void deposit(double amount) {realBankAccount.deposit(amount);}@Overridepublic void withdraw(double amount) {if ("ADMIN".equals(userRole)) {realBankAccount.withdraw(amount);} else {System.out.println("无权限取款");}}
    }// 客户端
    public class ProtectionProxyClient {public static void main(String[] args) {BankAccount adminAccount = new ProtectionProxy("ADMIN", 1000);adminAccount.withdraw(500);BankAccount userAccount = new ProtectionProxy("USER", 1000);userAccount.withdraw(500);}
    }
    

    输出结果

    取款成功,当前余额: 500.0
    无权限取款
    

总结
代理模式通过引入代理类为目标对象提供额外的功能或控制。它适用于延迟加载、权限控制、日志记录、远程调用等场景。代理模式可以分为静态代理和动态代理,并且具有多种变体,如虚拟代理、保护代理、远程代理等。

相关文章:

十二、结构型(代理模式)

代理模式(Proxy Pattern) 概念 代理模式(Proxy Pattern)是一种结构型设计模式,代理对象在不改变目标对象功能的前提下,通过控制对目标对象的访问,来实现延迟加载、权限控制、日志记录等功能。代…...

使用 python 下载 bilibili 视频

本文想要达成的目标为:运行 python 代码之后,在终端输入视频链接,可自动下载高清 1080P 视频并保存到相应文件夹。 具体可分为两大步:首先,使用浏览器开发者工具 F12 获取请求链接相关信息(根据 api 接口下…...

DevExpress WinForms中文教程:Data Grid - 如何点击获取信息?

在使用DevExpress WinForms的Data Grid之类控件时,可能需要实现自定义用户交互,例如显示数据行的上下文菜单,或者在双击一行时调用编辑表单。在这些情况下,您需要在指定的坐标处标识网格元素。 在本教程中,您将学习如…...

真空牛肉滚揉机的优点:

‌真空滚揉机是一种用于食品加工的设备,主要用于肉类深加工,如肉食制品和低温火腿的生产。‌ 它通过滚揉、按压和腌制的过程,在真空状态下将原料肉与辅料、添加剂均匀混合,以提高肉制品的质量和口感‌。 真空滚揉机的工作原理是利…...

【物流配送中心选址问题】基于退火算法混合粒子群算法

课题名称: 基于退火算法混合粒子群算法的物流配送中心选址问题 改进方向:模拟退火算法优化粒子群算法 代码获取方式(付费): 模型说明: 待补充 Matlab仿真结果: 1. 模型优化后的仿真结果 2…...

elasticsearch 8.2 版本账号密码设置及SSL设置

背景:elasticsearch 8.2 设置账号密码-CSDN博客 failed to load SSL configuration does not contain any trusted certificate entries [2024-10-08T17:06:53,704][ERROR][o.e.b.ElasticsearchUncaughtExceptionHandler] [node-1] uncaught exception in thread [main] org…...

git gui基本使用

一、图形化界面 二、创建新项目 创建文件,加入暂存区,提交到版本库 三、创建分支 四、合并分支 1.切换至master 五、更新分支 六、解决冲突 修改冲突,加入暂存区,提交到版本库 七、远程创建库 Gitee - 基于 Git 的代码托管和研…...

从automaxprocs库浅窥Linux容器的资源控制

automaxprocs能够自动调整Go程序中的Goroutine数量,以充分利用系统资源并提高程序的性能。 automaxprocs通过读取系统信息,如CPU核心数和Cgroups限制,来动态调整Goroutine的数量 automaxprocs获取CPU限额的关键方法在 // CPUQuotaToGOMAXP…...

AI 读文献(二):综述论文10倍速读和整理

我是娜姐 迪娜学姐 ,一个SCI医学期刊编辑,探索用AI工具提效论文写作和发表。 上一篇娜姐讲了research研究论文的速度框架和效果, AI阅读研究论文,这个方法10倍速提升效率还不损失关键信息! 学员们反馈效果很好&#x…...

【AAOS】Android Automotive 10模拟器源码下载及编译

源码下载 repo init -u https://android.googlesource.com/platform/manifest -b android-10.0.0_r47 repo sync -c --no-tags --no-clone-bundle 源码编译 source build/envsetup.sh lunch aosp_car_x86_64-userdebug make -j8 运行效果 emualtor Cluster Home Map All …...

前端开发攻略---使用css实现滚动吸附效果

实现代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>Document</title><style>…...

解析 MySQL 查询优化:提升性能的十个关键策略

1. 避免全表扫描 当查询的数据量非常大时&#xff0c;全表扫描的效率会很低。应尽量通过在WHERE和ORDER BY涉及的列上创建索引&#xff0c;避免全表扫描。索引就像一本书的目录&#xff0c;可以快速定位到需要的数据&#xff0c;而不用从头开始逐页查找。 示例&#xff1a; 如…...

QT--QPushButton设置文本和图标、使能禁能、信号演示

按钮除了可以设置显示文本之外&#xff0c;还可以设置图标 文本 可以获取和设置按钮上显示的文本 // 获取和设置按钮的文本 QString text() const void setText(const QString &text)该属性&#xff0c;既可以在 Qt 设计师右侧的属性窗口中修改&#xff0c;也可以在代码…...

PostgreSQL学习笔记六:模式SCHEMA

模式&#xff08;Schema&#xff09; PostgreSQL中的模式&#xff08;Schema&#xff09;是一个命名的数据库对象集合&#xff0c;包括表、视图、索引、数据类型、函数、存储过程和操作符等。模式的主要作用是组织和命名空间数据库对象&#xff0c;使得同一个数据库中可以包含…...

基础IO -- 理解文件(1)

目录 一&#xff1a;回顾文件 二&#xff1a;加深对文件的理解 1.概念 2.以w写方式打开 3.以a追加方式打开 4.重定向 一&#xff1a;回顾文件 以前学习过在C语言中的文件操作&#xff0c; 但那根本是不足以理解文件的&#xff0c;即站在语言角度是不可能理解文件的 我们要…...

golang包管理

package 在工程化的Go语言开发项目中&#xff0c;Go语言的源码复用是建立在包&#xff08;package&#xff09;基础之上的。本文介绍了Go语言中如何定义包、如何导出包的内容及如何导入其他包。 包与依赖管理 本章学习目标 掌握包的定义和使用掌握init初始化函数的使用掌握…...

outlook 添加企业邮箱账号出现 553 authentication is required 错误解决

系统报错如下 问题原因 发件服务器身份验证设置错误&#xff0c;或者未勾选发送服务器验证的选项。 解决方案 Outlook客户端 本文以Outlook 2016为例&#xff0c;具体操如下&#xff1a; 1、在Outlook客户端的电子邮件设置窗口中&#xff0c;单击其他设置&#xff1b; 2、…...

一个开源可本地部署的英文翻译服务----EnToZhAPI

EnToZhAPI项目简介 项目背景 提供本地化的英文翻译服务API。支持单句翻译请求或者批量翻译请求。支持建立查询词汇表。 项目架构 前端&#xff1a;使用原生js&#xff0c;使用MDB作为CSS框架。django模板引擎渲染可视化界面。 后端&#xff1a;使用waitress作为后端服务器…...

【unity】编辑器扩展——在OnValidate中创建、删除游戏物体

我们知道在OnValidate中创建游戏物体会发出警告&#xff0c;删除游戏物体会报错。 所以我们使用协程&#xff0c;将开始动作的信号放在OnValidate中&#xff0c;将动作的执行放在帧结尾。 参考代码如下&#xff1a; using System.Collections; using UnityEngine;public clas…...

学习记录:js算法(六十四):最后一块石头的重量

文章目录 最后一块石头的重量思路一思路二 最后一块石头的重量 有一堆石头&#xff0c;每块石头的重量都是正整数。 每一回合&#xff0c;从中选出两块 最重的 石头&#xff0c;然后将它们一起粉碎。假设石头的重量分别为 x 和 y&#xff0c;且 x < y。那么粉碎的可能结果如…...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

渲染学进阶内容——模型

最近在写模组的时候发现渲染器里面离不开模型的定义,在渲染的第二篇文章中简单的讲解了一下关于模型部分的内容,其实不管是方块还是方块实体,都离不开模型的内容 🧱 一、CubeListBuilder 功能解析 CubeListBuilder 是 Minecraft Java 版模型系统的核心构建器,用于动态创…...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

图表类系列各种样式PPT模版分享

图标图表系列PPT模版&#xff0c;柱状图PPT模版&#xff0c;线状图PPT模版&#xff0c;折线图PPT模版&#xff0c;饼状图PPT模版&#xff0c;雷达图PPT模版&#xff0c;树状图PPT模版 图表类系列各种样式PPT模版分享&#xff1a;图表系列PPT模板https://pan.quark.cn/s/20d40aa…...

Selenium常用函数介绍

目录 一&#xff0c;元素定位 1.1 cssSeector 1.2 xpath 二&#xff0c;操作测试对象 三&#xff0c;窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四&#xff0c;弹窗 五&#xff0c;等待 六&#xff0c;导航 七&#xff0c;文件上传 …...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧

上周三&#xff0c;HubSpot宣布已构建与ChatGPT的深度集成&#xff0c;这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋&#xff0c;但同时也存在一些关于数据安全的担忧。 许多网络声音声称&#xff0c;这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...

深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向

在人工智能技术呈指数级发展的当下&#xff0c;大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性&#xff0c;吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型&#xff0c;成为释放其巨大潜力的关键所在&…...