跳到主要内容

代理模式

介绍

代理模式(Proxy Pattern)是一种结构型设计模式,它提供了一个代理对象来控制对真实对象的访问。代理模式可以在不改变真实对象接口的情况下,为其添加额外的功能,如访问控制、延迟加载、日志记录等。

原理

代理模式的核心原理包括:

  1. 抽象主题:定义真实主题和代理主题的共同接口
  2. 真实主题:实现抽象主题,执行实际业务逻辑
  3. 代理主题:实现抽象主题,包含真实主题的引用,控制对真实主题的访问

图示

+----------------+        +----------------+
| Subject | | Client |
+----------------+ +----------------+
| + request() |<-------| + main() |
+-------^--------+ +----------------+
|
+-------+--------+ +----------------+
| RealSubject | | Proxy |
+----------------+ +----------------+
| + request() |<------| - realSubject |
+----------------+ | + request() |
+----------------+

代码示例

抽象主题

public interface Subject {
void request();
}

真实主题

public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("真实主题执行请求");
}
}

代理主题

public class Proxy implements Subject {
private RealSubject realSubject;

@Override
public void request() {
// 前置处理
beforeRequest();

// 调用真实主题
if (realSubject == null) {
realSubject = new RealSubject();
}
realSubject.request();

// 后置处理
afterRequest();
}

private void beforeRequest() {
System.out.println("代理: 请求前处理");
}

private void afterRequest() {
System.out.println("代理: 请求后处理");
}
}

客户端代码

public class Client {
public static void main(String[] args) {
Subject proxy = new Proxy();
proxy.request();
}
}

代理模式的类型

  1. 静态代理:编译时生成代理类
  2. 动态代理:运行时生成代理类
    • JDK动态代理:基于接口
    • CGLIB动态代理:基于继承
  3. 远程代理:控制对远程对象的访问
  4. 虚拟代理:延迟加载开销大的对象
  5. 保护代理:控制对对象的访问权限
  6. 缓存代理:为对象添加缓存功能
  7. 日志代理:记录对象的方法调用

动态代理示例(JDK)

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class DynamicProxyDemo {
public static void main(String[] args) {
RealSubject realSubject = new RealSubject();

Subject proxy = (Subject) Proxy.newProxyInstance(
realSubject.getClass().getClassLoader(),
realSubject.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method,
Object[] args) throws Throwable {
System.out.println("动态代理: 请求前处理");
Object result = method.invoke(realSubject, args);
System.out.println("动态代理: 请求后处理");
return result;
}
}
);

proxy.request();
}
}

解决方案

应用场景

  1. 访问控制:如权限验证
  2. 延迟加载:如虚拟代理
  3. 日志记录:记录方法调用信息
  4. 性能监控:统计方法执行时间
  5. 事务管理:为方法添加事务支持
  6. 缓存:缓存方法调用结果
  7. 远程调用:如RPC框架

最佳实践

  1. 接口隔离:代理类和真实类实现相同的接口
  2. 单一职责:每个代理类专注于一个功能
  3. 优先使用动态代理:减少代码量
  4. 结合工厂模式:创建代理对象

优缺点

优点

  • 保护真实对象
  • 增强真实对象功能
  • 控制访问权限
  • 实现延迟加载

缺点

  • 增加代码复杂度
  • 可能导致性能下降
  • 调试难度增加

工具推荐

  1. Java JDK:提供动态代理API
  2. CGLIB:高性能的代码生成库,用于创建动态代理
  3. Spring Framework:提供AOP支持,基于代理模式
  4. AspectJ:强大的AOP框架
  5. MyBatis:使用代理模式实现Mapper接口