设计模式Python版 代理模式

文章目录

  • 前言
  • 一、代理模式
  • 二、代理模式示例
  • 三、远程代理
  • 四、虚拟代理
  • 五、虚拟代理示例


前言

GOF设计模式分三大类:

  • 创建型模式:关注对象的创建过程,包括单例模式、简单工厂模式、工厂方法模式、抽象工厂模式、原型模式和建造者模式。
  • 结构型模式:关注类和对象之间的组合,包括适配器模式、桥接模式、组合模式、装饰模式、外观模式、享元模式和代理模式。
  • 行为型模式:关注对象之间的交互,包括职责链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式和访问者模式。

一、代理模式

代理模式(Proxy Pattern)

  • 定义:给某一个对象提供一个代理,并由代理对象控制对原对象的引用。

  • 解决问题:如何提供一种间接访问机制来实现对象的远程访问或受限访问?

  • 使用场景:

    • 当客户端对象需要访问远程主机中的对象时,可以使用远程代理。
    • 当需要用一个消耗资源较少的对象来代表一个消耗资源较多的对象,从而降低系统开销、缩短运行时间时,可以使用虚拟代理
    • 当需要控制对一个对象的访问,为不同用户提供不同级别的访问权限时,可以使用保护代理。
    • 当需要为某一个被频繁访问的操作结果提供一个临时存储空间,以供多个客户端共享访问这些结果时,可以使用缓冲代理
    • 当需要为一个对象的访问(引用)提供一些额外的操作时,可以使用智能引用代理
  • 组成:

    • Subject(抽象主题角色):它声明了真实主题和代理主题的共同接口,客户端通常需要针对抽象主题角色进行编程。
    • Proxy(代理主题角色):代理主题角色内部包含了对真实主题的引用,从而可以在任何时候操作真实主题对象。代理主题角色还可以控制对真实主题的使用,客户端在调用所引用的真实主题操作之前或之后还需要执行其他操作,而不仅仅是单纯调用真实主题对象中的操作。
    • RealSubject(真实主题角色):它定义了代理角色所代表的真实对象,在真实主题角色中实现了真实的业务操作,客户端可以通过代理主题角色间接调用真实主题角色中定义的操作。
  • 补充说明:

    • 由于某些原因,客户端不想或不能直接访问某个对象,此时可以通过一个被称为“代理”的第三者来实现间接访问,该方案对应的设计模式被称为代理模式。
    • 代理模式为对象的访问控制提供了一种设计方案,而且它具有多种不同的类型,应用相当广泛。
    • 在代理模式中引入了一个新的代理对象,代理对象可以在客户端对象和目标对象之间起到中介的作用,去掉客户不能看到的内容和服务或者增添客户需要的额外服务。
    • 代理模式和装饰模式比较
      • 代理模式主要是给真实主题类增加一些全新的职责,例如权限控制、缓冲处理、智能引用、远程访问等,这些职责与原有职责不属于同一个问题域
      • 装饰模式是通过装饰类为具体构件类增加一些相关的职责,是对原有职责的扩展,这些职责属于同一问题域。
    • 代理模式根据其目的和实现方式不同进行分类
      • 远程代理(Remote Proxy):为一个位于不同的地址空间的对象提供一个本地的代理对象
      • 虚拟代理(Virtual Proxy):如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建。
      • 保护代理(Protect Proxy):控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限。
      • 缓冲代理(Cache Proxy):为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。
      • 智能引用代理(Smart Reference Proxy):当一个对象被引用时,提供一些额外的操作,例如将对象被调用的次数记录下来等。
    • 代理模式是常用的结构型设计模式之一
  • 优点:

    • 一定程度上降低了系统的耦合度
    • 客户端可以针对抽象主题角色进行编程,增加和更换代理类无须修改源代码,符合开闭原则
    • 远程代理为位于两个不同地址空间对象的访问提供了一种实现机制
    • 虚拟代理通过一个消耗资源较少的对象来代表一个消耗资源较多的对象,可以在一定程度上节省系统的运行开销。
    • 保护代理可以控制对一个对象的访问权限,为不同用户提供不同级别的使用权限。
  • 缺点:

    • 实现代理模式需要额外的工作,有些代理模式的实现可能非常复杂

在这里插入图片描述

二、代理模式示例

使用代理模式设计和实现商务信息查询系统

  • 客户端对象通过代理对象间接访问具有商务信息查询功能的真实对象。在代理对象中除了调用真实对象的商务信息查询功能外,还增加了身份验证和日志记录等功能。
  • ProxySearcher充当代理主题角色,它是查询代理,维持了对RealSearcher对象、AccessValidator对象和Logger对象的引用
  • 属于智能引用代理
"""抽象角色"""class Searcher:def do_search(self, username: str, keyword: str, **kwargs) -> str:raise NotImplementedError"""真实角色"""class RealSearcher(Searcher):# 模拟查询商务信息def do_search(self, username, keyword, **kwargs):print(f"用户{username},使用关键词{keyword},查询商务信息!")return f"返回关于{keyword}具体内容""""代理角色"""class AccessValidator:# 身份验证业务类:模拟实现登录验证def validate(self, username, passwd) -> bool:if username == "张三" and passwd == "123":print(f"用户{username}登录成功!")return Trueelse:print(f"用户{username}登录失败!")return Falseclass Logger:# 日志记录业务类:模拟实现日志记录def log(self, username):print(f"更新数据库,用户{username}查询次数加1!")class ProxySearcher(Searcher):# 代理类def __init__(self):self.searcher = RealSearcher()  # 对真实主题对象的引用self.validator = AccessValidator()self.logger = Logger()def do_search(self, username, keyword, **kwargs):# 如身份验证成功,则执行查询if not kwargs or "passwd" not in kwargs:raise ValueError("未提供身份验证信息!")passwd = kwargs.get("passwd")if self.validator.validate(username, passwd): # 调用前:验证身份result = self.searcher.do_search(username, keyword)  # 调用真实主题对象self.logger.log(username)  # 调用后:记录查询日志return resultelse:return None
  • 客户端代码
searcher: Searcher = ProxySearcher()  # 针对抽象编,可将类名存储在配置文件config.json中
result = searcher.do_search("张三", "人工智能", passwd="123")
print(f"查找结果:{result}")
print("#" * 10)result = searcher.do_search("张三", "人工智能", passwd="123456")
print(f"查找结果:{result}")
print("#" * 10)result = searcher.do_search("张三", "人工智能")
print(f"查找结果:{result}")
print("#" * 10)
  • 输出结果
用户张三登录成功!
用户张三,使用关键词人工智能,查询商务信息!
更新数据库,用户张三查询次数加1!
查找结果:返回关于人工智能具体内容
##########
用户张三登录失败!
查找结果:None
##########
Traceback (most recent call last):
...raise ValueError("未提供身份验证信息!")
ValueError: 未提供身份验证信息!

三、远程代理

远程代理是一种常用的代理模式,它使得客户端程序可以访问在远程主机上的对象。

  • 客户端对象不能直接访问远程主机中的业务对象,只能采取间接访问的方式。
  • 远程业务对象在本地主机中有一个代理对象,该代理对象负责对远程业务对象的访问和网络通信,它对于客户端对象而言是透明的。
  • 客户端无须关心实现具体业务的是谁,只需要按照服务接口所定义的方式直接与本地主机中的代理对象交互即可。

在这里插入图片描述

四、虚拟代理

虚拟代理也是一种常用的代理模式。

  • 对于一些占用系统资源较多或者加载时间较长的对象,可以给这些对象提供一个虚拟代理。
  • 在真实对象创建成功之前虚拟代理扮演真实对象的替身,而当真实对象创建之后,虚拟代理将用户的请求转发给真实对象。
  • 使用场景
    • 由于对象本身的复杂性或者网络等原因导致一个对象需要较长的加载时间,此时可以用一个加载时间相对较短的代理对象来代表真实对象。
    • 当一个对象的加载十分耗费系统资源的时候,也非常适合使用虚拟代理。
  • 虚拟代理都是用一个“虚假”的代理对象来代表真实对象,通过代理对象来间接引用真实对象,从而在一定程度上提高系统的性能。

五、虚拟代理示例

使用虚拟代理设计图像加载器

  • 代理会在实际需要显示图像时才加载图像,而不是一开始就加载。
  • 实现延迟加载
"""抽象角色"""class ImageBase:def display(self):raise NotImplementedError"""真实角色"""class Image(ImageBase):def __init__(self, filename):self.filename = filenameself.load_image()def load_image(self):print(f"Loading {self.filename}")# 这里假设有一些加载图像的代码self.image = "Loaded Image"def display(self):print(f"Displaying {self.filename}")"""代理角色"""class ImageProxy(ImageBase):def __init__(self, filename):self.filename = filenameself.image = Nonedef display(self):if self.image is None:self.image = Image(self.filename)self.image.display()
  • 客户端代码
image: ImageBase = ImageProxy("《清明上河图》.jpg")
image.display()  # 调用时,再加载图像
image.display()  # 第二次调用时,不会重新加载图像
  • 输出结果
Loading 《清明上河图》.jpg
Displaying 《清明上河图》.jpg
Displaying 《清明上河图》.jpg

您正在阅读的是《设计模式Python版》专栏!关注不迷路~

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

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

相关文章

自动化测试(selenium篇)

🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 一、什么是自动化测试 自动化测试通俗一些来讲,就是相当于将人工测试手段进行转换,让代码去自动执行。 自动化测试主要分为:单元…

【大模型】DeepSeek与chatGPT的区别以及自身的优势

目录 一、前言二、核心技术对比2.1 模型架构设计2.1.1 ChatGPT的Transformer架构2.1.2 DeepSeek的混合架构 2.2 训练数据体系2.2.1 ChatGPT的数据特征2.2.2 DeepSeek的数据策略 三、应用场景对比3.1 通用场景表现3.1.1 ChatGPT的强项领域3.2.2 DeepSeek的专项突破 3.3 响应效率…

RK3568平台开发系列讲解(ConfigFS篇)ConfigFS核心数据结构

🚀返回专栏总目录 文章目录 一、数据结构二、结构体关系三、案例3.1、configfs_subsystem 实例3.2、config_group 实例化四、属性和方法五、config_item实例化沉淀、分享、成长,让自己和他人都能有所收获!😄 理解 ConfigFS 的核心数据结构对于深入使用和定制 ConfigFS 非…

Spring Boot Web 入门

目录 Spring Boot Web 是 Spring Boot 框架的一个重要模块,它简化了基于 Spring 的 Web 应用程序的开发过程。以下是一个 Spring Boot Web 项目的入门指南,涵盖了项目创建、代码编写、运行等关键步骤。 1. 项目创建 使用 Spring Initializr 使用 IDE …

网络工程师 (22)网络协议

前言 网络协议是计算机网络中进行数据交换而建立的规则、标准或约定的集合,它规定了通信时信息必须采用的格式和这些格式的意义。 一、基本要素 语法:规定信息格式,包括数据及控制信息的格式、编码及信号电平等。这是协议的基础,确…

【AI】在Ubuntu中使用docker对DeepSeek的部署与使用

这篇文章前言是我基于部署好的deepseek-r1:8b模型跑出来的 关于部署DeepSeek的前言与介绍 在当今快速发展的技术环境中,有效地利用机器学习工具来解决问题变得越来越重要。今天,我将引入一个名为DeepSeek 的工具,它作为一种强大的搜索引擎&a…

【Kubernetes Pod间通信-第1篇】在单个子网中使用underlay网络实现Pod到Pod的通信

Kubernetes中Pod间的通信 本系列文章共3篇: 【Kubernetes Pod间通信-第1篇】在单个子网中使用underlay网络实现Pod到Pod的通信(本文介绍)【Kubernetes Pod间通信-第2篇】使用BGP实现Pod到Pod的通信【Kubernetes Pod间通信-第3篇】Kubernetes中Pod与ClusterIP服务之间的通信…

Excel 融合 deepseek

效果展示 代码实现 Function QhBaiDuYunAIReq(question, _Optional Authorization "Bearer ", _Optional Qhurl "https://qianfan.baidubce.com/v2/chat/completions")Dim XMLHTTP As ObjectDim url As Stringurl Qhurl 这里替换为你实际的URLDim postD…

MacOS 安装NVM

MacOS 安装NVM 方法一:使用Homebrew安装nvm 打开终端(Terminal),输入以下命令安装Homebrew: /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"安装nvm…

采用idea中的HTTP Client插件测试

1.安装插件 采用idea中的HTTP Client插件进行接口测试,好处是不用打开post/swagger等多个软件,并且可以保存测试时的参数,方便后续继续使用. 高版本(2020版本以上)的idea一般都自带这个插件,如果没有也可以单独安装. 2.使用 插件安装完成(或者如果idea自带插件),会在每个Con…

LabVIEW铅酸蓄电池测试系统

本文介绍了基于LabVIEW的通用飞机铅酸蓄电池测试系统的设计与实现。系统通过模块化设计,利用多点传感器采集与高效的数据处理技术,显著提高了蓄电池测试的准确性和效率。 ​ 项目背景 随着通用航空的快速发展,对飞机铅酸蓄电池的测试需求也…

Python----Python高级(并发编程:协程Coroutines,事件循环,Task对象,协程间通信,协程同步,将协程分布到线程池/进程池中)

一、协程 1.1、协程 协程,Coroutines,也叫作纤程(Fiber) 协程,全称是“协同程序”,用来实现任务协作。是一种在线程中,比线程更加轻量级的存在,由程序员自己写程序来管理。 当出现IO阻塞时,…

go语言中的反射

为什么会引入反射 有时我们需要写一个函数,这个函数有能力统一处理各种值类型,而这些类型可能无法共享同一个接口,也可能布局未知,也有可能这个类型在我们设计函数时还不存在,这个时候我们就可以用到反射。 空接口可…

Mac电脑上好用的压缩软件

在Mac电脑上,有许多优秀的压缩软件可供选择,这些软件不仅支持多种压缩格式,还提供了便捷的操作体验和强大的功能。以下是几款被广泛推荐的压缩软件: BetterZip 功能特点:BetterZip 是一款功能强大的压缩和解压缩工具&a…

大学资产管理系统中的下载功能设计与实现

大学资产管理系统是高校信息化建设的重要组成部分,它负责记录和管理学校内所有固定资产的信息。随着信息技术的发展,下载功能成为提高资产管理效率的关键环节之一。 系统架构的设计是实现下载功能的基础。一个良好的系统架构能够确保数据的高效传输和存储…

UnityShader学习笔记——动态效果

——内容源自唐老狮的shader课程 目录 1.原理 2.Shader中内置的时间变量 3.Shader中经常会改变的数据 4.纹理动画 4.1.背景滚动 4.1.1.补充知识 4.1.2.基本原理 4.2.帧动画 4.2.1.基本原理 5.流动的2D河流 5.1.基本原理 5.2.关键步骤 5.3.补充知识 6.广告牌效果 …

Node.js 实现简单爬虫

介绍 爬虫是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。 本文将使用 Nodejs 编写一个简单的爬虫脚本,爬取一个美食网站,获取菜品的标题和图片链接,并以表格的形式输出。 准备工作 1、初始化项目 首先&#xff0…

JVM执行流程与架构(对应不同版本JDK)

直接上图(对应JDK8以及以后的HotSpot) 这里主要区分说明一下 方法区于 字符串常量池 的位置更迭: 方法区 JDK7 以及之前的版本将方法区存放在堆区域中的 永久代空间,堆的大小由虚拟机参数来控制。 JDK8 以及之后的版本将方法…

2025蓝桥杯JAVA编程题练习Day3

1.黛玉泡茶【算法赛】 问题描述 话说林黛玉闲来无事,打算在潇湘馆摆个茶局,邀上宝钗、探春她们一起品茗赏花。黛玉素来讲究,用的茶杯也各有不同,大的小的,高的矮的,煞是好看。这不,她从柜子里…

p5r预告信生成器API

p5r预告信生成器API 本人将js生成的p5r预告信使用go语言进行了重写和部署,并开放了其api,可以直接通过get方法获取预告信的png。 快速开始 http://api.viogami.tech/p5cc/:text eg: http://api.viogami.tech/p5cc/persona5 感谢p5r风格字体的制作者和…