跳转到内容

代理模式

来自代码酷

代理模式[编辑 | 编辑源代码]

代理模式(Proxy Pattern)是一种结构型设计模式,它为其他对象提供一种代理以控制对这个对象的访问。代理模式在不改变原始类代码的情况下,通过引入代理类来间接访问目标对象,从而实现对目标对象的保护、延迟加载、访问控制等功能。

模式结构[编辑 | 编辑源代码]

代理模式包含以下主要角色:

  • Subject(抽象主题):声明真实主题和代理主题的共同接口,客户端通过该接口访问真实主题。
  • RealSubject(真实主题):定义代理所代表的真实对象,是客户端最终要访问的对象。
  • Proxy(代理):持有对真实主题的引用,控制对真实主题的访问,并可能负责创建和删除它。

classDiagram class Subject { +request() } class RealSubject { +request() } class Proxy { -realSubject: RealSubject +request() } Subject <|-- RealSubject Subject <|-- Proxy Proxy --> RealSubject

代码示例[编辑 | 编辑源代码]

以下是一个简单的代理模式示例,展示如何通过代理控制对真实对象的访问:

// 抽象主题
interface Image {
    void display();
}

// 真实主题
class RealImage implements Image {
    private String filename;

    public RealImage(String filename) {
        this.filename = filename;
        loadFromDisk();
    }

    private void loadFromDisk() {
        System.out.println("Loading image: " + filename);
    }

    @Override
    public void display() {
        System.out.println("Displaying image: " + filename);
    }
}

// 代理
class ProxyImage implements Image {
    private RealImage realImage;
    private String filename;

    public ProxyImage(String filename) {
        this.filename = filename;
    }

    @Override
    public void display() {
        if (realImage == null) {
            realImage = new RealImage(filename); // 延迟加载
        }
        realImage.display();
    }
}

// 客户端代码
public class ProxyPatternDemo {
    public static void main(String[] args) {
        Image image = new ProxyImage("test.jpg");
        
        // 图像将从磁盘加载
        image.display();
        System.out.println("---");
        
        // 图像不需要再次加载
        image.display();
    }
}

输出结果:

Loading image: test.jpg
Displaying image: test.jpg
---
Displaying image: test.jpg

代理模式类型[编辑 | 编辑源代码]

代理模式有多种变体,常见的包括: 1. 虚拟代理:延迟创建开销大的对象(如上述图像加载示例)。 2. 保护代理:控制对原始对象的访问权限。 3. 远程代理:为位于不同地址空间的对象提供本地代表(如RPC调用)。 4. 智能引用代理:在访问对象时执行附加操作(如引用计数、线程安全检查等)。

实际应用案例[编辑 | 编辑源代码]

1. Spring AOP[编辑 | 编辑源代码]

Spring框架使用代理模式实现面向切面编程(AOP)。当使用@Transactional注解时,Spring会创建目标对象的代理,在方法调用前后添加事务管理逻辑。

2. 缓存代理[编辑 | 编辑源代码]

代理可以用于实现缓存机制,当客户端请求数据时,代理首先检查缓存,如果存在则直接返回,否则访问真实对象并将结果缓存。

class DataFetcher:
    def fetch_data(self, key):
        # 模拟耗时操作
        print(f"Fetching data for key: {key}")
        return f"Data for {key}"

class CachingProxy:
    def __init__(self, real_fetcher):
        self.real_fetcher = real_fetcher
        self.cache = {}

    def fetch_data(self, key):
        if key not in self.cache:
            self.cache[key] = self.real_fetcher.fetch_data(key)
        return self.cache[key]

# 使用示例
fetcher = CachingProxy(DataFetcher())
print(fetcher.fetch_data("user1"))  # 从真实对象获取
print(fetcher.fetch_data("user1"))  # 从缓存获取

优缺点[编辑 | 编辑源代码]

优点:

  • 可以在不修改目标对象的情况下扩展其功能
  • 将客户端与目标对象分离,降低系统耦合度
  • 可以实现精细化的访问控制
  • 支持延迟加载和按需创建对象

缺点:

  • 可能增加系统复杂度
  • 代理调用可能引入轻微的性能开销
  • 某些代理模式实现需要生成额外类(如动态代理)

数学表示[编辑 | 编辑源代码]

代理模式可以形式化表示为: {ClientProxy客户端访问代理ProxyRealSubject代理在必要时访问真实对象ProxyRealSubject代理与真实对象接口相同

总结[编辑 | 编辑源代码]

代理模式是一种强大的设计模式,它通过引入间接层提供了对目标对象的灵活控制。理解代理模式有助于开发者设计更灵活、可维护的系统架构,特别是在需要控制对象访问或添加横切关注点时。