跳到主要内容

代理模式

代理模式为其他对象提供一个代理,以控制对这个对象的访问。代理对象通常在客户端和目标对象之间起到中介作用,可以用于实现延迟加载、访问控制、日志记录等功能。

备注

读到这里也许会注意到代理模式和 装饰器模式 有些类似,但它们存在区别:

  • 代理模式为对象提供了相同的接口,装饰模式则为对象提供加强的接口
  • 代理通常自行管理其服务对象的生命周期,而装饰器的生成则总是由客户端进行控制。

结构

代理模式示意图代理模式示意图

代理模式中,客户端与高层接口交互,代理和原始服务对象都实现了这个接口。代理对象持有一个对服务对象的引用,客户端通过代理对象来访问服务对象。

应用场景

  • 延迟初始化(虚拟代理),将对象的初始化推迟到真正需要的时候
  • 访问控制(保护代理),控制对对象的访问
  • 本地执行远程调用(远程代理),代理对象在本地代表远程对象
  • 日志记录(日志代理),记录对对象的访问
  • 缓存数据(缓存代理),缓存对象的结果

优缺点

优点

  • 可以在控制服务对象的同时保证对客户端透明
  • 如果客户端对服务生命周期不关心,可以由代理对象自行管理
  • 开闭原则:可以在不对服务或客户端做出修改的情况下创建新代理。

缺点

  • 引入了额外的类,增加了代码复杂度
  • 可能存在性能问题,特别是在频繁访问代理对象时

代码示例

下面的代码示例展示了一个使用代理模式的 Python 示例。DatabaseExecutor 是一个接口,RealDatabaseExecutor 是实现了该接口的真实服务对象,它直接执行数据库查询。

DatabaseProxy 是代理类,它也实现了 DatabaseExecutor 接口。这个代理类控制对 RealDatabaseExecutor 的访问。它有两个主要功能:

  1. 访问控制:在执行查询之前,_check_access 方法会检查用户角色。只有 "admin" 用户才能执行查询。
  2. 延迟初始化RealDatabaseExecutor 对象直到第一次需要执行查询时才会被创建(_lazy_init),这可以节省资源。

客户端代码通过 DatabaseExecutor 接口与代理或真实对象进行交互,实现了对访问的控制和对客户端的透明。