什么是代理模式,用 Python 如何实现 Proxy(代理 或 Surrogate)对象结构型模式?

什么是代理模式?

代理(Proxy)是一种结构型设计模式,其目的是通过引入一个代理对象来控制对另一个对象的访问。代理对象充当目标对象的接口,这样客户端就可以通过代理对象间接地访问目标对象,从而在访问过程中实现一些额外的控制、功能或处理。

在这里插入图片描述


代理模式主要有三种类型:保护代理、虚拟代理和远程代理。

  1. 保护代理(Protection Proxy): 控制对真实对象的访问权限,允许或拒绝对真实对象的请求。例如,访问控制、身份验证等功能可以通过保护代理来实现。
+-----------------+       +---------------------+       +----------------+
|   Subject       |       |    RealSubject     |       |     Proxy      |
|   +request()    |<------|   +SensitiveOp()   |<------| +request()     |
+-----------------+       +---------------------+       +----------------+

这个简单的图示表达了保护代理的基本结构。在保护代理中,代理对象可以在调用真实主题的方法前后添加一些控制逻辑,例如检查权限,确保敏感操作只有在合适的条件下才能被执行。

  1. 虚拟代理(Virtual Proxy): 控制对目标对象的访问,延迟目标对象的创建或加载,以减少系统开销。例如,加载大型图像或复杂对象时,可以使用虚拟代理进行懒加载,只有在需要时才真正创建目标对象。
+-----------------+       +---------------------+       +----------------+
|   Subject       |       |    RealSubject     |       |     Proxy      |
|   +request()    |<------|   +loadImage()      |<------| +request()     |
+-----------------+       +---------------------+       +----------------+

在虚拟代理(Virtual Proxy)中,“虚拟”体现在代理对象不立即创建或加载真实对象,而是在需要的时候才进行。这种延迟加载的行为使得代理对象在不实际创建真实对象的情况下提供相同的接口。因此,"虚拟"表示的是代理对象对真实对象的懒加载特性。

  1. 远程代理(Remote Proxy): 在不同地址空间中代理对象,使得可以在不同的系统中进行远程通信。远程代理允许客户端访问位于远程服务器上的对象,而不必了解底层的网络细节。
+-----------------+       +---------------------+       +----------------+
|   Subject       |       |    RealSubject     |       |     Proxy      |
|   +request()    |<------|   +remoteRequest() |<------| +request()     |
+-----------------+       +---------------------+       +----------------+

在远程代理中,代理对象充当了客户端和真实对象之间的中介,使得客户端可以透明地访问位于远程服务器上的真实对象。代理负责处理网络通信、序列化和反序列化等远程调用的细节,使得客户端无需了解底层的网络细节,实现了对远程对象的透明访问。


代理模式的主要优势包括:

  • 控制访问: 代理对象可以控制客户端对目标对象的访问,从而增强安全性或实现访问控制。

  • 延迟加载: 使用虚拟代理可以延迟目标对象的创建,减少系统启动时间和资源占用。

  • 简化接口: 代理对象可以提供更简单的接口,隐藏目标对象的复杂性。

  • 远程访问: 远程代理使得客户端可以访问远程服务器上的对象,实现分布式系统中的远程通信。


代理模式的一般结构包括:

  • 抽象主题(Subject): 定义了代理和真实对象的共同接口,客户端通过该接口访问真实对象。

  • 真实主题(Real Subject): 实现了抽象主题接口,是代理所代表的真实对象。

  • 代理(Proxy): 实现了抽象主题接口,保存了对真实对象的引用,可以在客户端访问真实对象前后执行一些额外的操作。

代理模式的实现方式在不同编程语言中可能有所不同,但核心思想是引入一个中间层(代理对象)来控制对目标对象的访问。这样的设计提供了更好的灵活性和可维护性,允许在不修改客户端代码的情况下改变目标对象的行为或实现。

模式的意图

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

别名

Surrogate


在 Python 3 中,如何实现(Proxy)代理设计模式

在 Python 中实现代理(Proxy)设计模式相对简单,因为 Python 语言的特性和语法支持可以轻松地创建代理对象。下面是一个简单的例子,演示了如何实现保护代理(Protection Proxy):

# 抽象主题(Subject)
class Subject:def request(self):pass# 真实主题(Real Subject)
class RealSubject(Subject):def request(self):print("RealSubject: Handling request")# 代理(Proxy)
class Proxy(Subject):def __init__(self, real_subject):self._real_subject = real_subjectdef request(self):# 添加额外的控制逻辑print("Proxy: Checking access permissions.")if self._check_access():# 调用真实主题的方法self._real_subject.request()print("Proxy: Logging the request.")else:print("Proxy: Access denied.")def _check_access(self):# 模拟访问权限控制# 在实际应用中,这里可能会涉及更复杂的逻辑,如身份验证等return True  # 允许访问# 客户端代码
if __name__ == "__main__":real_subject = RealSubject()proxy = Proxy(real_subject)# 通过代理访问真实主题proxy.request()

在这个例子中:

  • Subject 是抽象主题,定义了代理和真实主题的共同接口。
  • RealSubject 是真实主题,实现了抽象主题的接口,表示真实的对象。
  • Proxy 是代理,包含一个对真实主题的引用,并在调用真实主题的方法前后添加了额外的控制逻辑。

在客户端代码中,我们首先创建了真实主题 RealSubject 和代理 Proxy 的实例,然后通过代理对象调用 request() 方法。代理对象会在调用真实主题的方法前后执行一些额外的操作,例如检查访问权限和记录请求。

这只是代理模式的一个简单示例,实际应用中可能涉及更复杂的场景和逻辑。代理模式可以根据具体的需求进行不同形式的实现,例如虚拟代理(Virtual Proxy)或远程代理(Remote Proxy)。


在实现代理模式时,有一些需要注意的地方:

  1. 接口一致性: 代理对象应该实现与真实对象相同的接口,以确保客户端能够无缝地切换代理和真实对象。

  2. 代理生命周期: 考虑代理对象和真实对象的生命周期。确保代理对象和真实对象的创建、销毁和状态管理都得到正确处理。

  3. 懒加载: 在虚拟代理中,确保真实对象的懒加载(延迟加载)逻辑正确实现,只有在需要时才真正创建或加载真实对象。

  4. 权限控制: 在保护代理中,确保代理对象正确地进行访问权限的控制,只有在符合条件时才允许客户端访问真实对象。

  5. 网络通信: 在远程代理中,要注意网络通信的问题,如处理超时、错误处理、序列化和反序列化等。

  6. 性能考虑: 使用代理模式可能引入一些性能开销,特别是在远程代理中。要仔细考虑性能需求,避免不必要的开销。

  7. 线程安全性: 如果在多线程环境中使用代理模式,确保代理对象的线程安全性,以避免潜在的并发问题。

  8. 代理组合: 考虑使用多个代理对象的组合,形成代理链。代理链可以实现更复杂的控制逻辑,但要注意确保每个代理的职责清晰且不重叠。

  9. 避免过度设计: 不要过度设计代理模式。根据实际需求,只添加必要的代理,以避免引入不必要的复杂性。

  10. 异常处理: 考虑代理对象和真实对象的异常处理。确保代理对象能够适当地处理异常,并在必要时传递给客户端。

总体来说,代理模式的实现需要根据具体场景灵活运用,确保代理对象能够正确地完成预期的功能,并且与真实对象协同工作。在设计和实现时,理清代理对象和真实对象的职责和关系是非常重要的。


本文就到这里了,感谢您的阅读 。别忘了点赞、收藏~ Thanks♪(・ω・)ノ 🍇

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

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

相关文章

【Python图像超分】Real-ESRGAN图像超分模型(超分辨率重建)详细安装和使用教程

1 前言 图像超分是一种图像处理技术&#xff0c;旨在提高图像的分辨率&#xff0c;使其具有更高的清晰度和细节。这一技术通常用于图像重建、图像恢复、图像增强等领域&#xff0c;可以帮助我们更好地理解和利用图像信息。图像超分技术可以通过多种方法实现&#xff0c;包括插值…

flutter报错: library “libflutter.so“ not found

修改android/app/build.gradle defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). applicationId "cn.rentsoft.flutter.openim.consumer" // You can update the …

CSS 文字溢出省略号显示

1. 单行文本溢出显示省略号 需要满足三个条件&#xff0c;添加对应的代码&#xff1a; &#xff08;1&#xff09;先强制一行内显示文本&#xff1b; &#xff08;2&#xff09;超出的部分隐藏&#xff1b; &#xff08;3&#xff09;文字用省略号来替代省略的部分&#xf…

IDEA 使用Reset Current Branch to Here 进行git 版本控制,图文操作

文章目录 一、总结区别&#xff08;只针对本地仓库操作&#xff09;Soft详细解释文件版本冲突处理 Mixed详细解释Hard详细解释Keep详细解释文件版本冲突处理 二、其他Revert commit 参考文档 一、总结区别&#xff08;只针对本地仓库操作&#xff09; Soft详细解释 Soft操作只…

docker命令大全

1、查看Docker 容器占用的空间 docker ps -s2、查看所有容器 docker ps -a3、启动、关闭、重启一个已存在的容器 docker start <容器ID> docker stop <容器ID> docker restart <容器ID> 4、进入容器&#xff0c;退出终端的时候不会关闭container的ma…

龙讯旷腾PWmat:新的催化反应机理——瞬态相变,对多相电催化剂的设计和多相电催化机理的研究具有重要意义

研究背景 众所周知&#xff0c;材料的性质&#xff0c;包括催化活性都是相敏感的。而材料的相与外界条件有关&#xff0c;电催化反应过程中的外部条件与反应前后的外部条件不同&#xff0c;这自然导致了一个问题&#xff1a;在反应过程中电催化剂的相是否可以与反应前后的相不…

注册按钮的点击事件

// 注册> 点击事件registerFn() {// js的兜底校验this.$refs.form.validate(async (valid) > {if (valid) {// 通过校验console.log(this.form);// 1.调用注册接口// 这里又是一个解构赋值&#xff0c;把axios返回的数据对象里data字段对应的值保存在res上const { data: …

C 语言数组

C 语言数组 在本教程中&#xff0c;您将学习如何使用数组。您将借助示例学习如何声明&#xff0c;初始化和访问数组的元素。 数组是可以存储多个值的变量。例如&#xff0c;如果要存储100个整数&#xff0c;则可以为其创建一个数组。 示例 cint data[100];如何声明数组&…

顺丰接口对接-订单创建与取消(java单元测试)

api文档 下单接口 &#xff1a;https://qiao.sf-express.com/Api/ApiDetails?level3393&interName%E4%B8%8B%E8%AE%A2%E5%8D%95%E6%8E%A5%E5%8F%A3-EXP_RECE_CREATE_ORDER 取消订单接口&#xff1a; https://qiao.sf-express.com/Api/ApiDetails?level3339&interNa…

算法-算法的基本框架思想

本文目录 算法的基本框架思想一、二叉树的基本框架1、二叉树的前序遍历2、二叉树的前序遍历优化2、二叉树的遍历基本框架 二、回溯算法的基本框架1、基本框架2、核心框架3、全排列的核心框架4、核心思想 三、动态规划的基本框架1、自顶向下递归的动态规划2、自顶向下递归的动态…

线程池的使用

线程池的作用 降低线程创建和销毁的开销&#xff1a;线程的创建和销毁是比较昂贵的操作。通过使用线程池&#xff0c;可以避免频繁地创建和销毁线程&#xff0c;而是复用线程池中已经存在的线程&#xff0c;从而降低了开销。 控制并发度&#xff1a;通过控制线程池中线程的数量…

【华为OD题库-009】食堂供餐-Java

题目 某公司员工食堂以盒饭方式供餐。为将员工取餐排队时间降低为0&#xff0c;食堂的供餐速度必须要足够快。现在需要根据以往员工取餐的统计信息&#xff0c;计算出一个刚好能达成排队时间为0的最低供餐速度。即&#xff0c;食堂在每个单位时间内必须至少做出多少份盒饭才能满…

ADC、DMA以及串口之间的联系和区别?

ADC、DMA和串口都是嵌入式系统中常用的模块&#xff0c;它们之间有以下联系和区别&#xff1a; 联系&#xff1a; ADC和DMA都是用于数据采集和传输的模块&#xff0c;ADC可以将模拟信号转换为数字信号&#xff0c;DMA可以在不经过CPU的情况下实现数据的高速传输。而串口则是一…

同城服务共享台球室小程序系统:打造智能化的台球体验

一、引言 随着科技的发展和人们生活节奏的加快&#xff0c;对于休闲娱乐的需求也在不断增长。台球作为一种广受欢迎的休闲活动&#xff0c;其智能化和便利性的需求也日益凸显。本文将探讨如何通过同城服务共享台球室小程序系统&#xff0c;打造智能化的台球体验。 二、系统设…

MySQL(14):视图

数据库对象 对象描述表(TABLE)表是存储数据的逻辑单元&#xff0c;以行和列的形式存在&#xff0c;列就是字段&#xff0c;行就是记录数据字典就是系统表&#xff0c;存放数据库相关信息的表。系统表的数据通常由数据库系统维护&#xff0c;程序员通常不应该修改&#xff0c;只…

mysql 讲解(1)

文章目录 前言一、基本的命令行操作二、操作数据库语句2.1、创建数据库2.2、删除数据库2.3、使用数据库2.4 查看所有数据库 三、列的数据类型3.1 字符串3.2 数值3.3 时间日期3.4 空3.5 int 和 varchar问题总结&#xff1a; 四、字段属性4.1 UnSigned4.2 ZEROFILL4.3 Auto_InCre…

ARPG----C++学习记录05 Section12 动画蒙太奇,收拿剑,MetaSound,调整动画

代码更新 https://github.com/BAOfanTing/ARPG_Game_Code/commit/c629270e49496ba1bcbaf03780d23c1842ca5e7a Animation Montages动画蒙太奇 蒙太奇的工作流程 新建一个鼠标左键的按键映射&#xff0c;下载一些攻击动画&#xff0c;重定向给我们的人物&#xff0c;新建一个动画…

PCL中的离群点去噪-StatisticalOutlierRemoval

作用是去除稀疏离群噪点。在采集点云的过程中&#xff0c;由于测量噪声的影响&#xff0c;会引入部分离群噪点&#xff0c;它们在点云空间中分布稀疏。在估算点云局部特征&#xff08;例如计算采样点处的法向量和曲率变化率&#xff09;时&#xff0c;这些噪点可能导致错误的计…

若依系统富文本框上传图片报错!

报错如下&#xff1a; 原因&#xff1a;如图&#xff0c;富文本路径中存在 / 字符&#xff0c;导致上传出错。 解决方案&#xff1a;将富文本框内容在前端进行加密&#xff0c;后端再解密。 前端&#xff1a; 安装 crypto-js 插件 npm install crypto-js 创建工具类 :在 sr…

使用MVS-GaN HEMT紧凑模型促进基于GaN的射频和高电压电路设计

标题&#xff1a;Facilitation of GaN-Based RF- and HV-Circuit Designs Using MVS-GaN HEMT Compact Model 来源&#xff1a;IEEE TRANSACTIONS ON ELECTRON DEVICES&#xff08;19年&#xff09; 摘要—本文阐述了基于物理的紧凑器件模型在研究器件行为细微差异对电路和系统…