什么是代理模式,用 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_subject

    def 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♪(・ω・)ノ 🍇

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【C++笔记】二叉搜索树的模拟实现

【C笔记】二叉搜索树的模拟实现 一、二叉搜索树的概念二、二叉搜索树的模拟实现2.0、定义二叉树节点2.1、非递归接口实现2.1.1、插入2.1.2、查找2.1.3、删除 2.2、递归接口实现2.2.1、插入2.2.2、查找2.2.3、删除 三、升级为K-V模型 一、二叉搜索树的概念 二叉搜索树的概念&am…

systemd-timesyncd

介绍 systemd-timesyncd 是一个用于跨网络同步系统时钟的守护服务。它实现了一个 SNTP 客户端。与NTP的复杂实现相比&#xff0c;这个服务简单的多&#xff0c;它只专注于从远程服务器查询然后同步到本地时钟。除非你打算为客户端提供 NTP 服务器或者连接本地硬件时钟&#xff…

【C++】C++的介绍及其发展史

初识C 一、什么是C&#xff0c;为什么会出现C二、C的发展史三、C的重要性3.1 语言的使用广泛度3.2 在工作领域 四、C的学习路径 及 书籍推荐 一、什么是C&#xff0c;为什么会出现C C语言是结构化和模块化的语言&#xff0c;适合处理较小规模的程序。 对于复杂的问题&#xff…

【python】sys-psth和模块搜索路径

我们在导入一个模块的时候&#xff0c;比如说&#xff1a; import math它必然是有搜索路径的&#xff0c;那到底是在哪个目录下面找呢&#xff1f;Python解释器去哪里找这个文件呢&#xff1f;只有找到这个文件才能读取、装载运行该模块文件。 它一般按照如下路径寻找模块文件…

混合A Star算法

混合A Star算法就是将A*与Lattice Graph相关联。 使用栅格地图&#xff0c;保持在栅格地图的这个节点方格里都只记录一个机器人的State&#xff0c;例如图上的弯弯的线&#xff0c;进行剪枝&#xff0c;看一个节点的Cost&#xff08;时间、消耗的能量、路径的长度、终端状态惩…

ElasticSearch学习和使用 (使用head软件可视化es数据)

使用步骤 直接使用 Elasticsearch的安装和使用 下载Elasticsearch6.2.2的zip包&#xff0c;并解压到指定目录&#xff0c;下载地址&#xff1a;https://www.elastic.co/cn/downloads/past-releases/elasticsearch-6-2-2运行bin目录下的elasticsearch.bat启动Elasticsearch安…

五个做原型的好处和意义

绘制原型不仅是产品开发的重要基础&#xff0c;也是UI设计师在设计过程中应该采用的主要路径标识。绘制原型的重要性不亚于建筑师手中的设计图纸&#xff01;虽然原型设计可能会给产品开发带来一些误解&#xff0c;但毫不夸张地说&#xff0c;任何开发人员都可以将优秀的开发产…

SMART PLC MODBUSTCP速度测试

SMART PLC MODBUSTCP通信详细介绍请参看下面文章链接: S7-200SMART PLC ModbusTCP通信(多服务器多从站轮询)_matlab sumilink 多个modbustcp读写_RXXW_Dor的博客-CSDN博客文章浏览阅读6.4k次,点赞5次,收藏10次。MBUS_CLIENT作为MODBUS TCP客户端通过S7-200 SMART CPU上的…

《015.SpringBoot+vue之音乐网》【前后端分离】

《015.SpringBootvue之音乐网》【前后端分离】 项目简介 [1]本系统涉及到的技术主要如下&#xff1a; 推荐环境配置&#xff1a;DEA jdk1.8 Maven MySQL 前后端分离; 后台&#xff1a;SpringBootMybatisMySQL; 前台&#xff1a;Vue3.0 TypeScript Vue-Router Vuex Axios …

C++ 运算符重载(Complex复数类)

Complex复数类 Complex.h #ifndef COMPLEX_H #define COMPLEX_H#include <iostream> using namespace std;class Complex { private:double real 0; //复数的实部double imag 0; //复数的虚部 public:Complex() default; /*无参构造*/Complex(double r); …

今起不再“没完没了的接龙斗嘴”

今天本“人民体验官”推广人民日报官方微博&#xff08;转央视网&#xff09;的文化产品《数字减负不能比减脂还难》。 截图&#xff1a;来源“人民体验官”推广平台 在时下的一些网络自媒体平台之上&#xff0c;的确存在“越拉越多的群&#xff0c;没完没了的接龙&#xff0c…

微信支付平台C#SDK_微信支付.net SDK

一、微信支付平台C# SDK V3 https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat/blob/main/docs/WechatTenpayV3 接口对应整理&#xff1a; https://github.com/fudiwei/DotNetCore.SKIT.FlurlHttpClient.Wechat/blob/main/docs/WechatTenpayV3/Basic_Mod…

计算机网络技术(一)

深入浅出计算机网络 微课视频_哔哩哔哩_bilibili 第一章概述 1.1 信息时代的计算机网络 1. 计算机网络各类应用 2. 计算机网络带来的负面问题 3. 我国互联网发展情况 1.2 因特网概述 1. 网络、互连网&#xff08;互联网&#xff09;与因特网的区别与关系 如图所示&#xff0…

Pinia 状态管理器 菠萝:Setup Store风格

Pinia介绍&#xff1a; Pinia 是 Vue 的专属状态管理库&#xff0c;它允许你跨组件或页面共享状态。 Pinia 大小只有 1kb 左右&#xff0c;超轻量级&#xff0c;你甚至可能忘记它的存在&#xff01; 相比 Vuex,Pinia 的优点&#xff1a; 更贴合 Vue 3 的 Composition API 风…

Android修行手册 - 可变参数中星号什么作用(冷知识)

点击跳转>Unity3D特效百例点击跳转>案例项目实战源码点击跳转>游戏脚本-辅助自动化点击跳转>Android控件全解手册点击跳转>Scratch编程案例点击跳转>软考全系列 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&…

Halcon WPF 开发学习笔记(2):Halcon导出c#脚本和WPF初步开发

文章目录 前言HalconC#教学简单说明如何二开机器视觉如何二次开发Halcon导出Halcon脚本新建WPF项目&#xff0c;导入Halcon脚本和Halcon命名空间 前言 我目前搜了一下我了解的机器视觉软件&#xff0c;有如下特点 优点缺点兼容性教学视频(B站前三播放量)OpenCV开源&#xff0…

TCSVT(IEEE Transactions on Circuits and Systems for Video Technology)期刊投稿指南

目录 TCSVT 期刊简介 TCSVT 期刊影响因子和分区​ 期刊官方网站 期刊投稿网址 投稿指南网址 稿件格式要求 稿件提交指南 A. 提交稿件 B. 手稿格式 C. 摘要指南 D. 提交图形的指南 E. 页面和彩色图形费用 TCSVT 期刊简介 IEEE Transactions on Circuits and Systems…

产品化的GPT,能否为“百模大战”照亮未来?

这两天&#xff0c;AI圈都处在一种莫名的震撼感当中。 北京时间 11月7日&#xff0c;OpenAI 举办了首次DevDay开发者日活动。活动现场发布了非常多内容&#xff0c;其中有一些按部就班的&#xff0c;比如技术上更新了最新版本的GPT-4 Turbo。也有一些让从业者目瞪口呆&#xff…

C语言数据结构-----双向链表增删查改的代码实现

文章目录 1.初始化双链表2.创建链表节点3.打印链表4.尾插5.尾删6.头插7.头删8.在pos之前插入8.1 在pos之前插入(改造头插)8.2 在pos之前插入(改造尾插) 9.删除pos位置9.1 删除pos位置(改造尾删)9.1 删除pos位置(改造头删) 10.查找11.毁灭 链接: 顺序表(动态顺序表增删查改的代码…

openGauss学习笔记-121 openGauss 数据库管理-设置密态等值查询-使用JDBC操作密态数据库

文章目录 openGauss学习笔记-121 openGauss 数据库管理-设置密态等值查询-使用JDBC操作密态数据库121.1 连接密态数据库121.2 调用isValid方法刷新缓存示例121.3 执行密态等值查询相关的创建密钥语句121.4 执行密态等值查询相关的创建加密表的语句121.5 执行加密表的预编译SQL语…