当前位置: 首页 > news >正文

Python设计模式:代理模式

1. 什么是代理模式

代理模式(Proxy Pattern)是一种结构型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。代理模式通过引入一个代理对象来间接访问真实对象,从而在不改变真实对象的情况下,增加对其访问的控制和管理。

在软件开发中,直接访问某个对象可能会涉及到复杂的操作、资源管理或安全问题。例如,在处理大型对象时,可能不希望在程序启动时就加载所有数据,而是希望在真正需要时才进行加载。此外,某些对象可能需要进行权限检查、日志记录或其他操作,这些都可以通过代理模式来实现。

代理模式的主要作用包括:

  1. 控制访问:代理可以在访问真实对象之前进行权限检查或其他控制,确保只有合适的请求才能访问真实对象。

  2. 延迟加载:通过代理,可以在需要时才加载真实对象,从而节省资源。例如,在处理大型数据时,可以使用代理来延迟对象的创建,直到真正需要时才进行初始化。

  3. 记录日志:代理可以在调用真实对象的方法时记录日志,方便后续的调试和分析。这对于监控系统的行为和性能非常有帮助。

  4. 远程代理:在分布式系统中,代理可以代表远程对象进行操作,隐藏网络通信的复杂性。客户端可以像访问本地对象一样访问远程对象,从而简化了编程模型。

  5. 缓存:代理可以实现对真实对象的结果进行缓存,以提高性能。例如,在网络请求中,代理可以缓存之前的请求结果,避免重复的网络调用。

2. 示例 1:图像加载代理

在实际开发中,图像加载是一个常见的场景,尤其是在图形用户界面(GUI)应用程序中。加载高分辨率图像可能会消耗大量的内存和时间,因此我们可以使用代理模式来实现延迟加载。

class RealImage:def __init__(self, filename):self.filename = filenameself.load_image_from_disk()def load_image_from_disk(self):print(f"Loading {self.filename}")def display(self):print(f"Displaying {self.filename}")class ProxyImage:def __init__(self, filename):self.filename = filenameself.real_image = Nonedef display(self):if self.real_image is None:self.real_image = RealImage(self.filename)  # 延迟加载self.real_image.display()if __name__ == "__main__":# 创建代理对象proxy_image = ProxyImage("test_image.jpg")# 第一次调用 display 方法时,图像会被加载proxy_image.display()# 再次调用 display 方法时,图像不会被重新加载proxy_image.display()
Loading test_image.jpg
Displaying test_image.jpg
Displaying test_image.jpg

3. 示例 2:网络请求代理

在现代应用程序中,网络请求是一个常见的场景。为了提高性能和安全性,我们可以使用代理模式来管理网络请求。以下是一个复杂的示例,展示如何使用代理模式来实现网络请求的缓存和日志记录。

import requests
import time
import json# 真实主题(Real Subject)
class RealNetworkRequest:def __init__(self, url):self.url = urldef fetch_data(self):print(f"Fetching data from {self.url}")response = requests.get(self.url)return response.json()# 代理(Proxy)
class ProxyNetworkRequest:def __init__(self, url, user_role):self.url = urlself.real_request = RealNetworkRequest(url)self.cache = {}self.log_file = "request_log.txt"self.user_role = user_role  # 用户角色def fetch_data(self):# 权限检查if not self.check_access():print("Access denied: You do not have permission to access this resource.")return None# 检查缓存if self.url in self.cache:print("Returning cached data.")return self.cache[self.url]# 记录请求开始时间start_time = time.time()# 发送请求data = self.real_request.fetch_data()# 将数据存入缓存self.cache[self.url] = data# 记录请求结束时间end_time = time.time()self.log_request(start_time, end_time)return datadef check_access(self):# 简单的权限检查逻辑# 这里可以根据实际需求进行更复杂的权限检查return self.user_role == "admin"  # 只有 admin 用户可以访问def log_request(self, start_time, end_time):duration = end_time - start_timelog_entry = f"Requested {self.url} in {duration:.2f} seconds\n"with open(self.log_file, "a") as log:log.write(log_entry)# 客户端代码
if __name__ == "__main__":url = "https://jsonplaceholder.typicode.com/posts/1"# 创建代理对象,用户角色为 "admin"proxy_request = ProxyNetworkRequest(url, user_role="admin")# 第一次调用 fetch_data 方法时,数据会被请求并缓存data = proxy_request.fetch_data()print("Data:", json.dumps(data, indent=2))# 再次调用 fetch_data 方法时,数据将从缓存中返回data = proxy_request.fetch_data()print("Data:", json.dumps(data, indent=2))# 创建代理对象,用户角色为 "guest"proxy_request_guest = ProxyNetworkRequest(url, user_role="guest")# 尝试调用 fetch_data 方法,应该会被拒绝data = proxy_request_guest.fetch_data()print("Data:", json.dumps(data, indent=2))
Fetching data from https://jsonplaceholder.typicode.com/posts/1
Data: {"userId": 1,"id": 1,"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit","body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}
Returning cached data.
Data: {"userId": 1,"id": 1,"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit","body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}
Access denied: You do not have permission to access this resource.
Data: null
  • 真实主题(RealNetworkRequest):负责发送网络请求并获取响应。
  • 代理(ProxyNetworkRequest)
    • 权限检查:在 fetch_data 方法中添加了 check_access 方法,检查用户角色是否为 “admin”。只有管理员用户才能访问网络请求。
    • 缓存和日志记录:与之前的示例相同,代理类在发送请求之前检查缓存,并在请求后记录日志。
  • 客户端代码:创建两个代理对象,一个是管理员用户,另一个是访客用户。管理员用户可以成功获取数据,而访客用户则会被拒绝访问。

http://www.mrgr.cn/news/96905.html

相关文章:

  • 2024年信息素养大赛 C++小学组初赛 算法创意实践挑战赛 真题答案解析
  • 查询条件与查询数据的ajax拼装
  • whisper 语音识别的安装与使用
  • LeetCode 解题思路 30(Hot 100)
  • GitHub高级筛选小白使用手册
  • Spring AI MCP Server + Cline 快速搭建一个数据库 ChatBi 助手
  • React-01React创建第一个项目(npm install -g create-react-app)
  • 【Unity】 HTFramework框架(六十四)SaveDataRuntime运行时保存组件参数、预制体
  • Transformer
  • Flinksql--订单宽表
  • [高级数据结构]线段树SegmentTree
  • React PDF 预览终极优化:30 页大文件不卡,加载快如闪电!
  • python操作es
  • UniApp集成极光推送详细教程
  • Python实现 MCP 客户端调用(高德地图 MCP 服务)查询天气工具示例
  • Laravel 中使用 JWT 作用户登录,身份认证
  • 【硬件视界9】网络硬件入门:从网卡到路由器
  • IO 端口与 IO 内存
  • Description of STM32F1xx HAL drivers用户手册
  • Mysql的安装