Appearance
代理模式(Proxy Pattern)
1. 官方定义
"Provide a surrogate or placeholder for another object to control access to it."
—— 《Design Patterns: Elements of Reusable Object-Oriented Software》(GoF, 1994)
核心:为其他对象提供一种代理以控制对这个对象的访问。
2. 模式解释
核心思想
- 访问控制:代理对象作为中间层,控制对真实对象的访问(如权限校验、延迟加载)。
- 透明性:客户端无感知代理与真实对象的差异,两者实现相同接口。
- 职责分离:代理类处理非核心逻辑(如日志、缓存),真实对象专注业务功能。
典型结构
plaintext
Client → |<<Interface>>|
Subject
△
| implements
┌───────────┴───────────┐
| |
RealSubject Proxy
△
| holds a RealSubject
优点
- 安全控制:保护真实对象不被直接访问(如防火墙代理)。
- 性能优化:延迟加载大资源(如图片懒加载)。
- 功能扩展:无侵入式添加日志、监控等横切关注点。
缺点
- 复杂度增加:引入额外类可能使系统结构复杂化。
- 调用链延长:代理转发请求可能导致性能损耗(如远程调用)。
3. 解决的问题
经典场景
- 远程代理(Remote Proxy)
- 访问远程对象(如 RPC 调用,客户端代理处理网络通信)。
- 虚拟代理(Virtual Proxy)
- 延迟加载大资源(如网页图片占位符,滚动到视图时加载真实图片)。
- 保护代理(Protection Proxy)
- 权限校验(如仅管理员可访问敏感数据)。
- 智能引用(Smart Reference)
- 自动清理缓存、统计访问次数等。
4. 实现注意事项
关键实现点
- 接口一致性
- 代理与真实对象必须实现相同接口(否则需适配器模式配合)。
- 代理类型选择
- 静态代理:手动编写代理类,适合简单场景。
- 动态代理:运行时生成代理类(如 JDK 动态代理、CGLIB)。
- 性能权衡
- 动态代理生成字节码有启动开销,但减少编码量。
代码示例(JDK 动态代理)
java
// 接口
interface Database {
void query(String sql);
}
// 真实对象
class RealDatabase implements Database {
public void query(String sql) { /* 执行查询 */ }
}
// 代理处理器
class LoggingHandler implements InvocationHandler {
private Database realDatabase;
public LoggingHandler(Database database) {
this.realDatabase = database;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("Log: Query executed - " + args[0]);
return method.invoke(realDatabase, args);
}
}
// 客户端调用
Database proxy = (Database) Proxy.newProxyInstance(
Database.class.getClassLoader(),
new Class[]{Database.class},
new LoggingHandler(new RealDatabase())
);
proxy.query("SELECT * FROM users");
5. 实现变体
类型 | 特点 | 适用场景 |
---|---|---|
静态代理 | 手动编写代理类,直接持有真实对象引用 | 代理逻辑简单,接口稳定 |
JDK 动态代理 | 基于接口生成代理类(需实现 InvocationHandler ) | 需要动态代理多个接口 |
CGLIB 动态代理 | 通过继承生成子类代理(可代理无接口的类) | 代理无接口的类 |
远程代理 | 处理网络通信和序列化(如 Java RMI) | 分布式系统调用 |
6. 相似模式对比
模式 | 核心区别 |
---|---|
装饰器模式 | 增强对象功能,代理模式控制对象访问 |
适配器模式 | 解决接口不兼容问题,代理模式保持接口一致 |
外观模式 | 简化复杂子系统访问,代理模式控制单个对象访问 |
7. 组合使用场景
常见搭配模式
- 工厂模式
- 场景:由工厂决定返回真实对象或代理(如根据配置启用缓存代理)。
- 单例模式
- 场景:代理类本身需全局唯一(如数据库连接池代理)。
- 观察者模式
- 场景:代理触发事件通知(如资源加载完成时通知监听器)。
总结
代理模式是系统访问控制的守门人,核心价值在于间接访问与逻辑解耦。其动态代理实现(如 Spring AOP)是 Java 生态的基石技术。需注意代理滥用导致的性能问题和过度设计风险,合理选择代理类型以平衡灵活性与复杂度。```