结构型 中等
代理模式
Proxy Pattern
为其他对象提供一种代理以控制对这个对象的访问。
概述
代理模式是一种结构型设计模式,让你能够提供对象的替代品或其占位符。代理控制着对于原对象的访问,并允许在将请求提交给对象前后进行一些处理。
适用场景
- •延迟初始化(虚拟代理)- 当你有一个偶尔使用的重量级服务对象时
- •访问控制(保护代理)- 当你需要根据不同客户端的权限控制对服务对象的访问时
- •本地执行远程服务(远程代理)- 当服务对象位于远程服务器上时
- •记录日志请求(日志记录代理)- 当你需要保存服务对象的请求历史记录时
- •缓存请求结果(缓存代理)- 当你需要缓存服务对象的请求结果并管理其生命周期时
- •智能引用(智能引用代理)- 当需要在对象被访问时执行额外操作(如引用计数)时
优点
- +可以在客户端毫无察觉的情况下控制服务对象
- +客户端与真实服务对象解耦,无需知道代理的存在
- +开闭原则:可以在不对服务或客户端做出修改的情况下创建新代理
- +单一职责原则:可以将服务实现与代理功能分离
- +可以在运行时切换代理和真实对象
缺点
- −代码可能变得复杂,因为需要引入许多新的类
- −服务响应可能会延迟,因为代理会增加一层间接访问
- −增加系统复杂度,需要维护代理和真实对象的一致性
结构
classDiagram
class Subject {
<<interface>>
+request()
}
class RealSubject {
+request()
}
class Proxy {
-realSubject: RealSubject
-accessControl()
-logging()
-caching()
+request()
}
class Client {
+main()
}
Subject <|.. RealSubject : implements
Subject <|.. Proxy : implements
Proxy o--> RealSubject : contains
Client ..> Subject : uses
style Subject fill:#e3f2fd,stroke:#1976d2,stroke-width:2px
style RealSubject fill:#e8f5e9,stroke:#388e3c,stroke-width:2px
style Proxy fill:#fff3e0,stroke:#f57c00,stroke-width:2px
style Client fill:#f5f5f5,stroke:#616161,stroke-width:1px
交互演示
代理控制对真实对象的访问
Client
Proxy
checklog
RealSubject
💤
lazy点击"通过代理访问"观察代理如何控制对真实对象的访问
生活类比
代理模式就像是现实生活中的各种代理服务,它们控制着对真实资源的访问,并在访问前后添加额外的功能。
信用卡
信用卡是银行账户的代理,它控制着对账户的访问,并可以在支付前后添加额外的功能(如积分、验证、信用检查)。你不需要随身携带大量现金(真实对象),只需使用信用卡(代理)即可完成支付。
安检门
机场安检门是登机口的代理。它控制着对登机口(真实对象)的访问,在允许通过前执行安全检查(额外功能)。
网页缓存
浏览器缓存是远程服务器的代理。当访问网页时,浏览器先检查本地缓存(代理),如果存在且未过期就直接使用,避免重复请求远程服务器(真实对象)。
代码实现
Example.java
实际应用
Java RMI(远程方法调用)
Java RMI 使用代理模式来访问远程对象。客户端使用 Stub(代理)与远程对象通信,Stub 负责网络通信的细节,对客户端透明。
Example.java
Spring AOP
Spring 框架的面向切面编程(AOP)使用代理模式实现。JDK 动态代理用于接口代理,CGLIB 用于类代理,在方法调用前后添加横切关注点(如事务、日志)。
Example.java
Hibernate 延迟加载
Hibernate 使用代理模式实现关联对象的延迟加载。当访问实体对象的关联集合时,返回的是代理对象,只有在真正访问数据时才从数据库加载。
Example.java
Android 的 Binder 机制
Android 的跨进程通信(IPC)使用 Binder 机制,其中 BinderProxy 是本地进程中的代理,负责将方法调用序列化后传递给远程的 Binder 对象。
Example.java
练习
1
代理模式的主要目的是什么?
2
以下哪些是代理模式的常见类型?
3
代理模式和装饰器模式的主要区别是什么?
4
在 Java 中,JDK 动态代理只能代理实现了接口的类
5