目录

  1. 代理模式简介
  2. 代理模式的结构
  3. 代理模式的优缺点
  4. 代理模式的实现
    • 4.1 Python 示例
  5. 代理模式的应用场景
  6. 出站链接
  7. 站内链接
  8. 参考资料

1. 代理模式简介

代理模式(Proxy Pattern) 是一种结构型设计模式,通过为其他对象提供代理对象来控制对这个对象的访问。代理对象是实际对象的“替身”,它可以在客户端和实际对象之间提供额外的功能,如延迟加载、访问控制、日志记录等。

为什么使用代理模式?

  • 控制访问:通过代理类可以在访问实际对象之前进行一些控制或优化,比如权限控制、懒加载等。
  • 增加功能:代理模式可以为目标对象提供附加的功能,如缓存、日志记录、事务控制等。
  • 解耦:客户端不直接依赖于目标对象,代理类可以在不同的环境中替换目标对象,提供灵活性。

典型应用

  • 虚拟代理:延迟加载对象的实例化,常用于图形图像加载、数据库连接等场景。
  • 远程代理:代表一个远程对象,通过代理来与远程系统交互。
  • 保护代理:控制对一个对象的访问,常用于访问控制或权限管理。
  • 缓存代理:提供对象的缓存功能,当对象访问频繁时,通过代理返回缓存的结果,而不是每次都创建新对象。

2. 代理模式的结构

代理模式通常包括以下角色:

角色作用
Subject(主题接口)定义代理类和真实对象共同实现的接口。
RealSubject(真实主题类)真实对象,代理模式最终通过该对象提供具体的服务。
Proxy(代理类)代理类,通过代理类访问真实对象,控制对真实对象的访问。
Client(客户端)客户端通过代理类与真实对象进行交互。

UML 类图

┌─────────────────────┐
│      Client        │
│  + operation()     │
└──────────▲─────────┘
           │
┌─────────────────────┐
│      Proxy        │  (代理类)
│  + operation()     │
└──────────▲─────────┘
           │
┌─────────────────────┐
│ RealSubject       │  (真实对象)
│  + operation()    │
└─────────────────────┘


3. 代理模式的优缺点

优点

  1. 控制对象访问:代理类可以控制对目标对象的访问,提供额外的功能(如权限控制、延迟加载等)。
  2. 提高性能:代理可以实现对象的懒加载或缓存机制,提高系统性能。
  3. 解耦:客户端不需要直接访问真实对象,代理对象在不同情况下可以替换真实对象,增强系统的灵活性和扩展性。

缺点

  1. 性能开销:代理对象可能会增加一定的性能开销,尤其是在访问频繁时,因为每次操作都需要通过代理类转发。
  2. 增加系统复杂性:引入代理模式可能会增加系统的复杂性,尤其是在代理类和真实对象之间的协调和管理上。

4. 代理模式的实现

4.1 Python 示例

场景:假设我们有一个RealSubject对象,它表示一个图像文件,而Proxy类可以在访问图像文件时实现延迟加载,即当图像文件需要显示时才进行加载。

# 1. 主题接口:图像显示接口
class Image:
    def display(self):
        pass

# 2. 真实主题类:真实图像类
class RealImage(Image):
    def __init__(self, filename):
        self.filename = filename
        self.load_image()

    def load_image(self):
        print(f"Loading image from {self.filename}")

    def display(self):
        print(f"Displaying image {self.filename}")

# 3. 代理类:图像代理类
class ProxyImage(Image):
    def __init__(self, filename):
        self.real_image = None
        self.filename = filename

    def display(self):
        if self.real_image is None:
            # 延迟加载图像
            self.real_image = RealImage(self.filename)
        self.real_image.display()

# 4. 客户端代码
if __name__ == "__main__":
    image = ProxyImage("example.jpg")

    # 第一次访问,图像会被加载
    image.display()  # 输出:Loading image from example.jpg  Displaying image example.jpg

    # 第二次访问,不需要加载图像
    image.display()  # 输出:Displaying image example.jpg

输出结果:

Loading image from example.jpg
Displaying image example.jpg
Displaying image example.jpg

在这个示例中,ProxyImage 是代理类,它在第一次访问时创建并加载实际的图像文件(RealImage)。此后,当客户端再次请求图像时,代理类直接显示图像,而不需要再次加载文件,从而实现了延迟加载。


5. 代理模式的应用场景

适用于以下情况

  1. 控制访问
    • 当需要控制对真实对象的访问时,代理模式能够提供访问控制功能,例如权限检查、日志记录、缓存等。
  2. 延迟加载
    • 当对象创建成本较高或者资源较为昂贵时,代理可以延迟对象的加载,直到真正需要使用时才加载。
  3. 远程服务访问
    • 代理模式可以用于远程方法调用(RPC)中,客户端通过代理访问远程服务器上的对象。
  4. 缓存代理
    • 当访问的对象内容不频繁变化时,可以通过代理类缓存对象的状态,避免重复计算或访问。

真实案例

  • 虚拟代理:在图形处理软件中,代理可以延迟加载图像,只有在图像需要显示时才加载。
  • 远程代理:客户端通过代理访问远程服务,代理类负责在本地和远程对象之间传递请求。
  • 保护代理:在一些系统中,代理类可以用来控制用户权限,只有具有足够权限的用户才能访问某些功能。

6. 出站链接

7. 站内链接

8. 参考资料

  • Gamma, E., Design Patterns: Elements of Reusable Object-Oriented Software (1994).
  • Freeman, E., Head First Design Patterns (2004).

总结

  • 代理模式通过为目标对象提供一个代理类,控制了对目标对象的访问,可以增强系统的灵活性和扩展性。
  • 代理模式适用于控制访问、延迟加载、远程访问、缓存等场景,例如虚拟代理、远程代理和保护代理。
  • 代理模式增加了设计的灵活性,但也可能导致性能开销和系统复杂度的增加。

如果你有更多问题或希望进一步探讨,欢迎继续交流!🚀