DEV Community

架构师小白
架构师小白

Posted on

代理模式深度指南:构建控制访问的艺术

代理模式深度指南:构建控制访问的艺术

在软件架构中,代理模式是一种结构型设计模式,它为另一个对象提供一个替代品或占位符,以控制对该对象的访问。本文将深入探讨代理模式的原理、实现方式和实战应用。

为什么需要代理模式?

想象一下,你需要访问一个远程服务。每次直接调用远程对象都会产生网络延迟。但如果你能在本地放置一个"替身",让它处理一些常见请求,只有必要时才真正访问远程服务,性能将大幅提升。

这就是代理模式的核心思想:用一个中介来控制对真实对象的访问

代理模式的组成

代理模式包含四个核心角色:

  1. Subject(抽象主题):定义了 RealSubject 和 Proxy 的公共接口
  2. RealSubject(真实主题):真正执行业务逻辑的对象
  3. Proxy(代理):持有 RealSubject 的引用,在需要时创建真实对象
  4. Client(客户端):通过 Proxy 访问真实对象

代理模式的类型

1. 远程代理 (Remote Proxy)

为远程对象在本地创建一个代理,隐藏网络访问细节。适用于需要调用分布式服务的场景。

客户端 → 本地代理 → 网络 → 远程服务
Enter fullscreen mode Exit fullscreen mode

2. 虚代理 (Virtual Proxy)

延迟加载,只在真正需要时才创建开销大的对象。这就像网购时的"待发货"状态——先显示占位,等需要时才真正加载。

class VirtualProxy Image:
    def __init__(self, url):
        self.url = url
        self._real_image = None

    def display(self):
        # 首次调用时才加载真实图片
        if not self._real_image:
            self._real_image = RealImage(self.url)
        self._real_image.display()
Enter fullscreen mode Exit fullscreen mode

3. 保护代理 (Protection Proxy)

控制对真实对象的访问权限,在调用前进行身份验证。这类似于公司门禁系统——检查访客是否有权限进入。

4. 智能引用代理 (Smart Reference Proxy)

在访问对象时附加额外操作,比如:

  • 记录调用次数
  • 缓存计算结果
  • 懒加载关联对象

5. 缓存代理 (Cache Proxy)

为重复访问的结果提供缓存,避免重复计算。这就像浏览器的缓存机制——首次加载后保存在本地,后续直接使用。

Python 实现示例

from abc import ABC, abstractmethod
import time

# 抽象主题
class Image(ABC):
    @abstractmethod
    def display(self):
        pass

# 真实主题
class RealImage(Image):
    def __init__(self, filename):
        self.filename = filename
        self._load_from_disk()

    def _load_from_disk(self):
        print(f"正在加载图片: {self.filename}")
        time.sleep(1)  # 模拟加载时间
        print("加载完成!")

    def display(self):
        print(f"显示图片: {self.filename}")

# 虚拟代理
class ProxyImage(Image):
    def __init__(self, filename):
        self.filename = filename
        self._real_image = None

    def display(self):
        if self._real_image is None:
            self._real_image = RealImage(self.filename)
        self._real_image.display()

# 使用示例
print("=== 第一次显示 ===")
img = ProxyImage("photo.jpg")
img.display()

print("\n=== 第二次显示 ===")
img.display()
Enter fullscreen mode Exit fullscreen mode

运行结果:

=== 第一次显示 ===
正在加载图片: photo.jpg
加载完成!
显示图片: photo.jpg

=== 第二次显示 ===
显示图片: photo.jpg
Enter fullscreen mode Exit fullscreen mode

代理模式 vs 装饰器模式

特性 代理模式 装饰器模式
目的 控制访问 动态添加功能
关系 替代真实对象 包装真实对象
创建时机 预先创建 运行时包装
客户端感知 无缝替换 功能增强

实际应用场景

1. 数据库连接池

连接池本身就是一种代理模式——预先创建一批连接,客户端从代理获取连接,用完归还,而不是每次都创建新连接。

2. API 限流

在高并发系统中,使用代理实现 API 限流,保护后端服务:

class RateLimitedProxy:
    def __init__(self, real_service, max_requests, time_window):
        self.real_service = real_service
        self.max_requests = max_requests
        self.time_window = time_window
        self.requests = []

    def call(self, *args, **kwargs):
        now = time.time()

        # 清理过期请求记录
        self.requests = [t for t in self.requests if now - t < self.time_window]

        if len(self.requests) >= self.max_requests:
            raise Exception("请求过于频繁,请稍后再试")

        self.requests.append(now)
        return self.real_service.execute(*args, **kwargs)
Enter fullscreen mode Exit fullscreen mode

3. 考试系统防作弊

在在线考试系统中,代理可以:

  • 检测切屏次数
  • 限制复制粘贴
  • 记录异常行为

4. 微服务健康检查

代理可以监控下游服务状态,在服务不可用时返回缓存数据或降级响应。

总结

代理模式是一种强大的架构工具,它的核心价值在于:

  1. 解耦 - 将访问逻辑与业务逻辑分离
  2. 增强 - 可以无感地添加日志、缓存、限流等功能
  3. 控制 - 实现访问控制、权限验证
  4. 优化 - 通过懒加载和缓存提升性能

掌握代理模式,让你在设计系统时多一件利器!


下篇预告:策略模式 (Strategy Pattern) - 让算法 interchangeable 的艺术

如果你对这个系列感兴趣,欢迎关注并留言讨论你想了解的设计模式!

💡 提示:合理使用代理模式可以显著提升系统性能和安全性,但切记不要过度设计。只有当真正需要控制访问时,才考虑使用代理。

Top comments (0)