Python代理模式介绍、使用
一、Python代理模式介绍
Python代理模式(Proxy Pattern)是一种结构型设计模式。在代理模式中,代理对象充当了另一个对象的占位符,以控制对该对象的访问。
代理对象和被代理对象实现了相同的接口,因此它们可以互相替代。客户端和代理对象之间的交互是无缝的,因为它们的接口是一样的。
代理模式的主要功能是为其他对象提供一个代理,以控制对对象的访问。代理对象可以在调用被代理对象之前或之后执行一些操作,例如身份验证,缓存等。
优点:
- 保护了真实对象的访问,可以对访问进行限制和控制;
- 可以提高访问效率,通过代理对象可以缓存数据或者调用其他服务等;
- 可以提高系统的灵活性,因为代理对象可以在不影响真实对象的情况下扩展其功能。
缺点:
- 可能引入额外的复杂性,因为需要创建代理对象。
- 此外,如果代理对象没有正确实现与真实对象相同的接口,可能会导致客户端代码无法正常工作。
应用场景:
- 身份验证:在访问某些敏感数据或操作时,可以使用代理对象执行身份验证,以确保用户有权访问该数据或执行该操作。
- 缓存:使用代理对象来缓存数据,以便在下一次访问时可以更快地访问数据。
- 远程服务:代理对象可以用作远程服务的本地代表,在使用远程服务时提供更好的用户体验,同时也可以提高访问效率。
代理模式可以通过组合或继承实现。通常,代理对象会继承与真实对象相同的接口,并在继承的方法中调用真实对象的方法。
二、代理模式使用
工作原理:
- 客户端代码通过代理对象调用真实对象。
- 代理对象执行一些额外的操作(例如身份验证或缓存),然后调用真实对象的方法。
- 真实对象执行所请求的操作,并将结果返回给代理对象。
- 代理对象将结果返回给客户端代码。
示例一:实现缓存功能
假设我们正在开发一个网络应用程序,该应用程序可以向外提供图片资源。由于图片资源较大,我们希望通过代理模式来缓存这些数据,以提高程序的性能和响应速度。
下面是一个基于Python的实现示例:
from abc import ABC, abstractmethod# 定义抽象基类
class Image():@abstractmethoddef display(self):pass# 定义具体子类,继承Image,重新display方法
class RealImage(Image):def __init__(self, filename): # 构造函数,接收一个参数filenameself.filename = filename # 文件名保存在filename实例变量中self.load_from_disk() # 调用load_from_disk()方法,从磁盘中加载图片数据'''从磁盘中加载图片数据子类RealImage独有的方法由于这个过程比较耗时,因此我们需要在初始化时进行加载,避免在图片显示时等待。'''def load_from_disk(self): #print("loading " + self.filename)# 显示图片def display(self):print("Displaying " + self.filename)# 定义代理类,继承Image,重写display方法
class ImageProxy(Image):def __init__(self, filename):self.filename = filename# 定义真实图片self.real_image = Nonedef display(self):if self.real_image is None:# 如果没有加载真实图片# 调用具体子类RealImage, 创建真实图片对象, 缓存真实对象,避免重复加载图片资源self.real_image = RealImage(self.filename)# 显示真实图片self.real_image.display()image = ImageProxy("test.jpg")
print("第一次调用display方法:图片没有加载真实图片,调用子类RealImage, 创建真实图片对象")
image.display()
print("第二次调用display方法: 直接从缓存中获取图片")
image.display()
运行结果:
第一次调用display方法:图片没有加载真实图片,调用子类RealImage, 创建真实图片对象
loading test.jpg
Displaying test.jpg
第二次调用display方法: 直接从缓存中获取图片
Displaying test.jpg
在上面的示例中,我们定义了一个抽象基类Image,其中包含一个display()抽象方法。接着,我们定义了一个具体子类RealImage,它代表了真实的图片对象,负责从磁盘中加载图片数据,并提供display()方法用于显示图片。
我们还定义了一个代理类ImageProxy,它也实现了Image接口。当客户端调用display()方法时,代理类会检查是否已经加载了真实的图片对象。如果没有,代理会先创建一个真实的图片对象,然后再调用它的display()方法。这样,代理对象就可以缓存真实对象,避免了重复加载图片资源,从而提高程序性能。
使用代理模式时,客户端代码只需要与代理对象交互,并不需要知道真实对象的存在。当代理对象需要访问真实对象时,它会自动创建并调用真实对象,从而实现对真实对象的间接访问。
示例二:实现身份验证功能
在Python中,使用代理模式实现身份验证功能可以参考以下示例代码:
# 定义抽象主题类
class AbstractSubject():def request(self):pass# 定义子类真实主题对象,继承抽象主题类
class RealSubject(AbstractSubject):def request(self):print("RealSubject: 处理请求...")# 定义代理类, 继承抽象主题类
class Proxy(AbstractSubject):def __init__(self, realsubject: RealSubject, username: str, password: str):self._subject = realsubjectself._username = usernameself._password = passworddef request(self):if self.authenticdate():self._subject.request() # 调用子类request方法else:print("代理认证失败")def authenticdate(self):# 模拟身份认证过程if self._username == "admin" and self._password == "admin123456":print("代理认证成功")return Trueelse:return False# 创建真实主题对象
real_subject = RealSubject()# 创建代理对象
proxy = Proxy(real_subject, "admin", "admin123456")
# 通过代理对象发送请求
proxy.request()# 修改代理认证信息,再次发送请求
proxy._username = "a"
proxy._password = "b"
proxy.request()
运行结果:
代理认证成功
RealSubject: 处理请求...
代理认证失败
在上述示例代码中,我们定义了一个抽象主题类AbstractSubject和其子类RealSubject,并在代理类Proxy中持有一个真实主题对象_subject。在客户端调用时,通过代理对象proxy发送请求。
在代理类中,我们重写了request()方法,在其中添加了身份验证的逻辑。如果身份验证成功,则代理对象将请求转发给真实主题对象;否则,代理对象将输出代理认证失败的消息。
代理类Proxy的构造函数包含三个参数:
realsubject参数是真实主题对象,使用类型提示指定为RealSubject类。username参数是用于身份认证的用户名,使用类型提示指定为字符串类型。password参数是用于身份认证的密码,使用类型提示指定为字符串类型。
在代理类的构造函数中,将输入的真实主题对象、用户名和密码保存到对应的成员变量中,以便后续使用。
在客户端调用过程中,我们创建了一个真实主题对象real_subject和代理对象proxy,并通过代理对象发送请求。我们可以通过修改代理认证信息,测试代理类的身份验证功能是否正常工作。
示例三:实现远程服务功能
以下是一个示例代码,演示了如何使用 Python 代理模式实现远程服务功能:
from abc import ABC, abstractmethod# 定义抽象类:远程服务接口
class RemoteService():@abstractmethoddef request(self, param: str) -> str: # 抽象方法:接受字符串类型参数,返回字符串类型结果pass# 实现远程服务
class RemoteServiceIml(RemoteService):def request(self, param: str) -> str:return f"Remote service received {param}"# 实现代理类
class RemoteServiceProxy(RemoteService):def __init__(self, remote_service: RemoteService):self._remote_service = remote_servicedef request(self, param: str) -> str:print("Remote service aouthentication...")# 调用远程服务器前,本地操作...,例如:身份认证、参数校验if not param:raise ValueError("Missing parameter")# 调用远程服务,返回结果return self._remote_service.request(param)remote_service_impl = RemoteServiceIml()
proxy = RemoteServiceProxy(remote_service_impl)res = proxy.request("test")
print(res)
运行结果:
Remote service aouthentication...
Remote service received test
在上述代码中,我们首先定义了一个远程服务接口RemoteService,其中有一个request方法,用于处理远程服务请求,返回一个字符串类型的结果。同时,我们还实现了RemoteServiceImpl类,该类用于实现具体的远程服务逻辑。在具体的request方法中,简单地将接收到的参数拼接成一条消息,并返回。
接下来,我们使用代理模式实现了RemoteServiceProxy类,该类也实现了RemoteService接口,并接收一个RemoteService实例作为构造函数参数。当我们调用request方法时,代理类先进行身份认证、参数校验等本地操作,然后再调用远程服务,最后将结果返回。
在使用示例中,我们先创建了RemoteServiceImpl的实例,然后将它传入代理类的构造函数中创建代理对象proxy。最后,我们调用代理对象的request方法,传入一个字符串参数,并将返回结果打印出来。这个例子展示了代理模式如何在应对远程服务时起到的作用。
def request(self, param: str) -> str:解释:
这段代码是一个抽象方法的定义,其中request是一个接受一个字符串类型的参数,返回一个字符串类型的结果的抽象方法,但是该方法没有具体实现,只是提供了一个方法头。这种方法被称为抽象方法,是一种在抽象类中定义,需要在子类中具体实现的方法。在Python中,我们可以通过定义抽象类和使用abstractmethod装饰器来实现抽象方法的定义。子类必须实现抽象类中的所有抽象方法才能被实例化,并且子类中的抽象方法也可以再次定义为抽象方法,以继续在更深层次上实现多态行为。
raise ValueError("Missing parameter")解释:
这段代码是一个异常抛出语句,当代码执行到此处时,会抛出一个ValueError类型的异常,并传递一个字符串参数"Missing parameter"作为异常信息。异常机制是Python中的一种错误处理机制,当程序出现错误时,可以使用异常机制提前中止程序的运行,并在异常发生的地方引发一个异常对象,这样就可以将错误信息传递给上层调用的代码,以便于更好地处理错误。在Python中,可以使用raise语句抛出一个异常对象,从而使得程序进入异常处理流程。
相关文章:
Python代理模式介绍、使用
一、Python代理模式介绍 Python代理模式(Proxy Pattern)是一种结构型设计模式。在代理模式中,代理对象充当了另一个对象的占位符,以控制对该对象的访问。 代理对象和被代理对象实现了相同的接口,因此它们可以互相替代…...
《MySQL45讲》笔记—索引
索引 索引是为了提高数据查询效率,就像书的目录一样。如下图,索引和数据就是位于存储引擎中: 索引常见模型 哈希表 以键值对存储的数据结构。适用于只有等值查询的场景。 有序数组 在等值查询和范围查询场景中性能都特别优秀。但是有…...
Android usb host模式通信示例
当使用Android设备作为USB主机时,可以使用Android提供的USB API来进行USB通信。下面是一个简单的Android USB通信的示例。在这个示例中,我们将发送一条消息到连接的USB设备并从USB设备接收响应。 首先,在AndroidManifest.xml文件中添加以下权…...
开源Blazor UI组件库精选:让你的Blazor项目焕然一新!
今天给大家推荐一些开源、美观的Blazor UI组件库,这些优秀的开源框架和项目不仅能够帮助开发者们提高开发效率,还能够为他们的项目带来更加丰富的用户体验。 注:排名不分先后,都是十分优秀的开源框架和项目 Ant Design Blazor…...
MATLAB RANSAC圆柱体点云拟合 (28)
MATLAB RANSAC圆柱体点云拟合 (28) 一、算法介绍二、函数介绍三、算法实现四、效果展示一、算法介绍 RANSAC拟合方法,从原始点云中拟合具有特定形状的点云,这里对原始点云中大致呈圆柱的点云进行分割,圆柱的半径,以及朝向都是比较重要的定义圆柱的参数。下面是具体使用的…...
【AI】《动手学-深度学习-PyTorch版》笔记(七):自动微分
AI学习目录汇总 1、什么是自动微分 自动微分:automatic differentiation,深度学习框架通过自动计算导数,即自动微分,自动微分使系统能够随后反向传播梯度。 计算图:computational graph,根据设计好的模型,系统会构建一个计算图, 来跟踪计算是哪些数据通过哪些操作组合…...
vuejs源码阅读之代码生成器
代码生成器是模版编译的最后以后,它的作用是将AST转换成渲染函数中的内容,这个内容可以称为代码字符串。 代码字符串可以被包装在函数中执行,这个函数就是我们通常说的渲染函数。 渲染函数被执行之后,可以生成一份VNode…...
【MySQL】视图(十)
🚗MySQL学习第十站~ 🚩本文已收录至专栏:MySQL通关路 ❤️文末附全文思维导图,感谢各位点赞收藏支持~ 一.引入 视图(View)是一种虚拟存在的表。视图中的数据并不在数据库中实际存在,行和列数据…...
面试手写实现Promise.all
目录 前言常见面试手写系列Promise.resolve 简要回顾源码实现Promise.reject 简要回顾源码实现Promise.all 简要回顾源码实现Promise.allSettled 简要回顾源码实现Promise.race 简单回顾源码实现结尾 前言 (?﹏?)曾经真实发生在一个朋友身上的真实事件,面试官让…...
TCP网络通信编程之字符流
【案例1】 【题目描述】 【 注意事项】 (3条消息) 节点流和处理流 字符处理流BufferedReader、BufferedWriter,字节处理流-BufferedInputStream和BufferedOutputStream (代码均正确且可运行_Studying~的博客-CSDN博客 1。这里需要使用字符处理流,来将…...
佰维存储面向旗舰智能手机推出UFS3.1高速闪存
手机“性能铁三角”——SoC、运行内存、闪存决定了一款手机的用户体验和定位,其中存储器性能和容量对用户体验的影响越来越大。 针对旗舰智能手机,佰维推出了UFS3.1高速闪存,写入速度最高可达1800MB/s,是上一代通用闪存存储的4倍以…...
降龙十八掌
目录 大数据: 1 HIVE: 1.1 HIVE QL 1.1.1 创建表 1.1.2 更新表 1.1.3 常用语句 1.2 hive参数配置 大数据: 1 HIVE: 1.1 HIVE QL DDL中常用的命令有:create,drop,alter,trunc…...
【项目设计】MySQL 连接池的设计
目录 👉关键技术点👈👉项目背景👈👉连接池功能点介绍👈👉MySQL Server 参数介绍👈👉功能实现设计👈👉开发平台选型👈👉MyS…...
Ubuntu系统adb开发调试问题记录
Ubuntu系统adb开发调试问题记录 一、adb devices no permissions二、自定义adb server端口三、动态库目录四、USB抓包 一、adb devices no permissions lsusb -t 设备树直观地查看设备的Bus ID和Device Num,lsusb找到对应的PID和VID编辑udev规则 sudo vim /etc/ud…...
【宏定义】——检验条件是否成立,并返回指定的值
文章目录 功能说明实现示例解析扩展 功能说明 宏检验条件是否成立,并返回指定的值 #define TU_VERIFY(...) _GET_3RD_ARG(__VA_ARGS__, TU_VERIFY_2ARGS, TU_VERIFY_1ARGS, UNUSED)(__VA_ARGS__)TU_VERIFY(1) 检验为真,啥也不干TU_VERIFY(0) 校验为假&…...
UE5引擎源码小记 —反射信息注册过程
序 最近看了看反射相关的知识,用不说一点人话的方式来说,反射是程序在运行中能够动态获取修改或调用自身属性的东西。 一开始我是觉得反射用处好像不大,后续查了下一些反射的使用环境,发现我格局小了,我觉得用处不大的…...
Redis缓存预热
说明:项目中使用到Redis,正常情况,我们会在用户首次查询数据的同时把该数据按照一定命名规则,存储到Redis中,称为冷启动(如下图),这种方式在一些情况下可能会给数据库带来较大的压力…...
Android 耗时分析(adb shell/Studio CPU Profiler/插桩Trace API)
1.adb logcat 查看冷启动时间和Activity显示时间: 过滤Displayed关键字,可看到Activity的显示时间 那上面display后面的是时间是指包含哪些过程的时间呢? 模拟在Application中沉睡1秒操作,冷启动情况下: 从上可知&…...
保护隐私与安全的防关联、多开浏览器
随着互联网的不断发展,我们越来越离不开浏览器这个工具,它为我们提供了便捷的网络浏览体验。然而,随着我们在互联网上的活动越来越多,我们的个人信息和隐私也日益暴露在网络风险之下。在这种背景下,为了保护个人隐私和…...
CloudStudio搭建Next框架博客_抛开电脑性能在云端编程(沉浸式体验)
文章目录 ⭐前言⭐进入cloud studio工作区指引💖 注册coding账号💖 选择cloud studio💖 cloud studio选择next.js💖 安装react的ui框架(tDesign)💖 安装axios💖 代理请求跨域&#x…...
C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
Day131 | 灵神 | 回溯算法 | 子集型 子集
Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣(LeetCode) 思路: 笔者写过很多次这道题了,不想写题解了,大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
Redis数据倾斜问题解决
Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中,部分节点存储的数据量或访问量远高于其他节点,导致这些节点负载过高,影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
