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

代理模式主要有三种类型:保护代理、虚拟代理和远程代理。
- 保护代理(Protection Proxy): 控制对真实对象的访问权限,允许或拒绝对真实对象的请求。例如,访问控制、身份验证等功能可以通过保护代理来实现。
+-----------------+ +---------------------+ +----------------+
| Subject | | RealSubject | | Proxy |
| +request() |<------| +SensitiveOp() |<------| +request() |
+-----------------+ +---------------------+ +----------------+
这个简单的图示表达了保护代理的基本结构。在保护代理中,代理对象可以在调用真实主题的方法前后添加一些控制逻辑,例如检查权限,确保敏感操作只有在合适的条件下才能被执行。
- 虚拟代理(Virtual Proxy): 控制对目标对象的访问,延迟目标对象的创建或加载,以减少系统开销。例如,加载大型图像或复杂对象时,可以使用虚拟代理进行懒加载,只有在需要时才真正创建目标对象。
+-----------------+ +---------------------+ +----------------+
| Subject | | RealSubject | | Proxy |
| +request() |<------| +loadImage() |<------| +request() |
+-----------------+ +---------------------+ +----------------+
在虚拟代理(Virtual Proxy)中,“虚拟”体现在代理对象不立即创建或加载真实对象,而是在需要的时候才进行。这种延迟加载的行为使得代理对象在不实际创建真实对象的情况下提供相同的接口。因此,"虚拟"表示的是代理对象对真实对象的懒加载特性。
- 远程代理(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)。
在实现代理模式时,有一些需要注意的地方:
-
接口一致性: 代理对象应该实现与真实对象相同的接口,以确保客户端能够无缝地切换代理和真实对象。
-
代理生命周期: 考虑代理对象和真实对象的生命周期。确保代理对象和真实对象的创建、销毁和状态管理都得到正确处理。
-
懒加载: 在虚拟代理中,确保真实对象的懒加载(延迟加载)逻辑正确实现,只有在需要时才真正创建或加载真实对象。
-
权限控制: 在保护代理中,确保代理对象正确地进行访问权限的控制,只有在符合条件时才允许客户端访问真实对象。
-
网络通信: 在远程代理中,要注意网络通信的问题,如处理超时、错误处理、序列化和反序列化等。
-
性能考虑: 使用代理模式可能引入一些性能开销,特别是在远程代理中。要仔细考虑性能需求,避免不必要的开销。
-
线程安全性: 如果在多线程环境中使用代理模式,确保代理对象的线程安全性,以避免潜在的并发问题。
-
代理组合: 考虑使用多个代理对象的组合,形成代理链。代理链可以实现更复杂的控制逻辑,但要注意确保每个代理的职责清晰且不重叠。
-
避免过度设计: 不要过度设计代理模式。根据实际需求,只添加必要的代理,以避免引入不必要的复杂性。
-
异常处理: 考虑代理对象和真实对象的异常处理。确保代理对象能够适当地处理异常,并在必要时传递给客户端。
总体来说,代理模式的实现需要根据具体场景灵活运用,确保代理对象能够正确地完成预期的功能,并且与真实对象协同工作。在设计和实现时,理清代理对象和真实对象的职责和关系是非常重要的。
本文就到这里了,感谢您的阅读 。别忘了点赞、收藏~ Thanks♪(・ω・)ノ 🍇
相关文章:
什么是代理模式,用 Python 如何实现 Proxy(代理 或 Surrogate)对象结构型模式?
什么是代理模式? 代理(Proxy)是一种结构型设计模式,其目的是通过引入一个代理对象来控制对另一个对象的访问。代理对象充当目标对象的接口,这样客户端就可以通过代理对象间接地访问目标对象,从而在访问过程…...
国内领先的五大API接口供应商
API(Application Programming Interface)接口,现在很多应用系统中常用的开放接口,对接相应的系统、软件功能,简化专业化的程序开发。作者用过的国内比较稳定的API接口供应商有如下几家,大家可以参考选择&am…...
第十九章 Java绘图
一,Java绘图类 19.1.1Graphics类 Graphics类是所有图形上下文的抽象基类,它允许应用程序在组件以及闭屏图像上进行绘制。 可实现直线,矩形,多边形,椭圆,圆弧等形状和文本,图片的绘制制作。 …...
【C++面向对象】13. 接口 / 抽象类*
文章目录 【 1. 抽象类 】1.1 抽象类的定义1.2 抽象类的应用条件1.3 实例 【 2. 设计策略 】 接口描述了类的行为和功能,而不需要完成类的特定实现。C 接口是使用 抽象类(abstract base class,也称为ABC) 来实现的。 【 1. 抽象类…...
LeetCode热题100——二分查找
二分查找 1. 搜索插入位置2. 搜素二维矩阵3. 在排序数组中查找第一个和最后一个元素位置 1. 搜索插入位置 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 // 题…...
使用VC++实现分段线性变换,直方图均衡化、锐化处理(使用拉普拉斯算子)
图像锐化1 实验要求 5.1实验目的、要求 实验目的: (1)掌握图像增强的原理与相关方法。 (2)能使用VC实现图像增强的一些相关功能。 实验要求: A部分: (1)对一幅256级灰度…...
react class改hooks写法
类头修改 export default class EditUseTable extends Component 改为 export default function EditUseTable({})参数修改 constructor(props) {super(props)const {dbRecord, type, currentRecord, readOnly, updateTaxAmount} this.props改为(主函数的参数&a…...
桂院校园导航 | 云上高校导航 云开发项目 二次开发教程 1.3
Gitee代码仓库:桂院校园导航小程序 GitHub代码仓库:GLU-Campus-Guide 演示视频 中国大学生计算机设计大赛-移动应用与开发-云上高校导航 升级日志 1.3 优化了小程序的数据存储方式,对部分页面进行了调整,调整了功能和代码。 引…...
sscanf提取相应字符到数组
代码如下 #include<stdio.h> #include<string.h>int main(int argc, char const *argv[]) {char buf[128] {0};int m1 0, m2 0;int s1 0, s2 0;char lrc[128] "";sscanf("[02:16.33][04:11.44]我想大声宣布对你恋恋不舍","[%*1d%d…...
本地开发环境和服务器传输数据的几种方法
❤️觉得内容不错的话,欢迎点赞收藏加关注😊😊😊,后续会继续输入更多优质内容❤️ 👉有问题欢迎大家加关注私戳或者评论(包括但不限于NLP算法相关,linux学习相关,读研读博…...
LeetCode之二叉树
发现更多计算机知识,欢迎访问Cr不是铬的个人网站 最近数据结构学到二叉树,就刷了刷力扣,写这篇文章也是辅助记忆。 103二叉树锯齿形遍历 要解出本道题,首先要会层次遍历。层次遍历我们都知道用一个队列去实现就行。但是力扣这里…...
论文学习——THE USTC SYSTEM FOR ADRESS-M CHALLENGE
文章目录 引言正文Abstract模型基本结构模型效果汇总 Introduction介绍跨语言任务的独特性思路启发和变化如何使用预定义好的音频特征如何使用预定义好的语言模型——语言模型中获取韵律信息结果说明 Dataset数据集Mthods方法使用设计好的特征进行AD检测使用的特征分类和训练方…...
第一百七十五回 如何创建放射形状渐变背景
文章目录 1. 概念介绍2. 实现方法3. 代码与效果3.1 示例代码3.2 运行效果 4. 内容总结 我们在 上一章回中介绍了"如何创建扇形渐变背景"相关的内容,本章回中将介绍" 如何创建放射形状渐变背景"。闲话休提,让我们一起Talk Flutter吧…...
vue实现调用手机拍照、录像功能
目录 前言 准备工作 在这个示例中,我们将使用Vue.js框架来实现我们的目标。如果你还不熟悉Vue.js,推荐先学习一下Vue.js的基础知识。 接下来,我们需要创建一个基于Vue.js的项目。你可以使用Vue CLI来创建一个全新的Vue项目:# 安…...
WPF播放视频
在WPF中,你可以使用MediaElement来播放本地视频。下面是一个简单的例子: <Window x:Class"WPFVideoPlayer.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsof…...
交换机如何配置BGP协议
环境: 华为交换机 华三交换机 问题描述: 交换机如何配置BGP协议 解决方案: 华三交换机上配置案例 1.配置BGP协议,可以按照以下步骤进行: 登录交换机:使用SSH、Telnet或控制台等方式登录到华三交换…...
精通Nginx(14)-配置HTTPS
HTTPS是在 HTTP 协议的基础上使用 TLS/SSL 加密,其主要目标是提高数据传输的安全性。从HTTP2.0开始,HTTPS已经是网站的标准协议,很多开放平台非HTTPS不能访问。Nginx为HTTPS提供了强大的支持,且对应用服务器是完全透明的。 目录 SSL/TLS基础 发展历史 TLS握手过程 加密…...
封装一个简单的table组件
子组件 <template> <el-table :data"tableData" :headers"tableHeaders" style"width: 100%"> <el-table-column v-for"header in tableHeaders" :key"header.prop" :label"header.label" :pro…...
Avalonia UI框架介绍
Avalonia UI是一个跨平台的UI框架,它允许开发者使用XAML和C#语言创建可在多个平台上运行的应用程序,包括Windows、Linux、macOS等。Avalonia UI与WPF非常相似,但是它是开源的,并且更加灵活。 下面是一个简单的Avalonia UI应用程序…...
【入门篇】1.3 redis客户端之 jedis 高级使用示例
文章目录 0.前言1. 发布和订阅消息2. 事务操作3. 管道操作4. jedis 支持哨兵模式5. jedis 支持集群模式5. 参考链接 0.前言 Jedis是Redis的Java客户端,它支持所有的Redis原生命令,使用方便,且可以与Java项目无缝集成。 该库的最新版本支持Re…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
C++使用 new 来创建动态数组
问题: 不能使用变量定义数组大小 原因: 这是因为数组在内存中是连续存储的,编译器需要在编译阶段就确定数组的大小,以便正确地分配内存空间。如果允许使用变量来定义数组的大小,那么编译器就无法在编译时确定数组的大…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
多模态图像修复系统:基于深度学习的图片修复实现
多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...
从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践
作者:吴岐诗,杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言:融合数据湖与数仓的创新之路 在数字金融时代,数据已成为金融机构的核心竞争力。杭银消费金…...
