设计模式实战:代理模式(Proxy)

在很多系统中,我们并不会直接访问某个对象,而是通过一个"中间层"来完成访问。

例如:

  • 访问远程服务(RPC)
  • 数据库懒加载
  • 权限控制
  • 缓存代理
  • 日志记录

客户端看起来是在访问对象本身,但实际上中间有一层"代理"。

这就是 代理模式(Proxy)


一、代理模式解决什么问题?

一句话:

为一个对象提供一个替身(代理),以控制对该对象的访问。

关键词:

  • 控制访问
  • 延迟加载
  • 权限控制
  • 远程访问

代理对象与真实对象实现 相同接口,客户端并不知道自己访问的是代理还是原对象。


二、一个典型场景:图片懒加载

假设系统中需要加载图片,但图片文件很大:

  • 加载速度慢
  • 占用内存
  • 可能根本不会被使用

如果直接创建对象:

python 复制代码
class RealImage:

    def __init__(self, filename):
        self.filename = filename
        self.load_from_disk()

    def load_from_disk(self):
        print(f"加载图片: {self.filename}")

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

创建对象时就会立即加载:

python 复制代码
image = RealImage("photo.jpg")

如果系统中有很多图片,这会严重影响性能。


三、引入代理对象

我们可以创建一个代理类,在真正需要时才加载图片。

python 复制代码
class ImageProxy:

    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()

使用方式:

python 复制代码
image = ImageProxy("photo.jpg")

# 此时并不会加载图片
image.display()

输出:

复制代码
加载图片: photo.jpg
显示图片: photo.jpg

图片只有在 真正使用时才加载

这就是 虚拟代理(Virtual Proxy)


四、代理模式结构

代理模式通常包含三个角色:

1️⃣ Subject(抽象接口)

定义真实对象与代理对象的共同接口。

2️⃣ RealSubject(真实对象)

真正执行业务逻辑的对象。

3️⃣ Proxy(代理对象)

控制对真实对象的访问。

结构示意:

复制代码
Client
  |
Proxy
  |
RealSubject

客户端只依赖接口,不关心具体实现。


五、Python 版本的完整示例

先定义统一接口:

python 复制代码
from abc import ABC, abstractmethod

class Image(ABC):

    @abstractmethod
    def display(self):
        pass

真实对象:

python 复制代码
class RealImage(Image):

    def __init__(self, filename):
        self.filename = filename
        self.load()

    def load(self):
        print(f"加载图片: {self.filename}")

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

代理对象:

python 复制代码
class ImageProxy(Image):

    def __init__(self, filename):
        self.filename = filename
        self.real_image = None

    def display(self):

        if not self.real_image:
            self.real_image = RealImage(self.filename)

        self.real_image.display()

客户端:

python 复制代码
image = ImageProxy("test.jpg")

print("对象创建完成")

image.display()

运行结果:

复制代码
对象创建完成
加载图片: test.jpg
显示图片: test.jpg

可以看到:

  • 对象创建时没有加载图片
  • 第一次访问才真正创建对象

六、代理模式常见类型

代理模式有很多变种,常见的包括:

1 虚拟代理(Virtual Proxy)

控制资源加载,例如:

  • 图片懒加载
  • 大对象初始化

2 远程代理(Remote Proxy)

代表远程对象,例如:

  • RPC 调用
  • 微服务客户端
  • gRPC

客户端看起来像调用本地对象,其实是远程调用。


3 保护代理(Protection Proxy)

控制访问权限,例如:

  • 用户权限校验
  • API 权限控制

示例:

python 复制代码
if not user.is_admin:
    raise PermissionError

4 缓存代理(Cache Proxy)

在访问真实对象前增加缓存。

例如:

  • Redis 缓存
  • API 缓存
  • 查询缓存

七、代理模式 vs 装饰器模式

很多人会混淆这两个模式。

对比 代理模式 装饰器模式
目的 控制访问 增强功能
是否强调叠加 不强调 强调
使用场景 权限、远程、懒加载 日志、缓存、监控

一句话总结:

代理关注"控制访问",装饰器关注"增强功能"。


八、真实项目中的应用

代理模式在真实项目中非常常见。

例如:

1 ORM 懒加载

在 Django / SQLAlchemy 中:

python 复制代码
user.posts

第一次访问才会查询数据库。


2 RPC 客户端

调用远程服务:

python 复制代码
user_service.get_user(1001)

看起来像本地调用,其实是网络请求。


3 缓存代理

python 复制代码
def get_user(id):

    if cache.exists(id):
        return cache.get(id)

    user = db.query(id)
    cache.set(id, user)

    return user

缓存层本质上就是代理。


九、代理模式优缺点

优点

  • 控制对象访问
  • 支持懒加载
  • 可以增加权限控制
  • 可以加入缓存

缺点

  • 增加系统复杂度
  • 代理类可能变多
  • 调试时层级增加

十、一句话总结

代理模式的核心是:为对象增加一个"中间层",控制对对象的访问。

这个中间层可以实现:

  • 权限控制
  • 懒加载
  • 远程调用
  • 缓存

在现代系统中,代理模式几乎无处不在。

相关推荐
xixihaha13242 小时前
实战:用OpenCV和Python进行人脸识别
jvm·数据库·python
badhope2 小时前
Python 库全景图:核心工具与最佳实践(小白也能看懂版)
后端·python
带娃的IT创业者2 小时前
WeClaw WebSocket 路由实战:BridgeConnectionManager 如何用四层映射在 800 个连接中实现毫秒级消息转发?
网络·python·websocket·网络协议·fastapi·实时通信
Storynone2 小时前
【Day】LeetCode:134. 加油站,135. 分发糖果,860. 柠檬水找零,406. 根据身高重建队列
python·算法·leetcode
阿_旭2 小时前
基于YOLO26深度学习的茶叶病害智能检测识别系统【python源码+Pyqt5界面+数据集+训练代码】
人工智能·python·深度学习·茶叶病害检测
好家伙VCC2 小时前
**NumPy中的高效数值计算:从基础到进阶的实战指南**在现代数据科学与机器学习领域
java·python·机器学习·numpy
荷蒲2 小时前
【小白量化机器人】爬取财经新闻并利用本地大模型评分选择合适交易策略
人工智能·python·机器学习·ai·金融·本地大模型
&变形记¥2 小时前
openclaw升级/重启
python
ewboYang2 小时前
自学全栈搭建python [fastapi] + uniapp [vue3+ts]项目
python·uni-app·fastapi