Java设计模式——代理模式
⚪代理模式(Proxy)是一种结构型设计模式,代理对象通常充当另一个对象的接口,以控制对该对象的访问,同时也可以添加一些额外的功能。代理模式在软件开发中经常被使用,例如在实现远程代理、虚拟代理、缓存代理等方面。
⚪意图:为其他对象提供一种代理,以控制对这个对象的访问。
⚪以下是工厂方法模式的关键要点:
▷ 角色和责任:
- 抽象主题(Subject):定义了代理对象和真实主题的共同接口,客户端通过这个接口来访问真实主题。
- 真实主题(Real Subject):实际执行工作的类,是代理模式中的关键对象。
- 代理(Proxy):充当了真实主题和客户端之间的中介,控制对真实主题的访问,并可以在访问前后执行一些额外的操作。
▷ 工作流程:
- 客户端创建一个代理对象,而不是直接创建真实主题对象。
- 当客户端通过代理对象调用方法时,代理对象会将请求传递给真实主题对象。
- 在传递请求之前或之后,代理对象可以执行一些额外的操作,例如权限检查、日志记录等。
- 真实主题对象执行请求,并将结果返回给代理对象。
- 代理对象将结果返回给客户端,客户端不需要知道它正在与代理对象交互。
▷ 示例
// 1. 抽象主题
interface Image {
void display();
}
// 2. 真实主题
class RealImage implements Image {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadFromDisk();
}
private void loadFromDisk() {
System.out.println("Loading image from disk: " + filename);
}
public void display() {
System.out.println("Displaying image: " + filename);
}
}
// 3. 代理
class ProxyImage implements Image {
private RealImage realImage;
private String filename;
public ProxyImage(String filename) {
this.filename = filename;
}
public void display() {
if (realImage == null) {
realImage = new RealImage(filename);
}
realImage.display();
}
}
// 客户端
public class ProxyPatternExample {
public static void main(String[] args) {
Image image1 = new ProxyImage("image1.jpg");
Image image2 = new ProxyImage("image2.jpg");
// 图像仅在首次显示时加载
image1.display();
image1.display(); // 不会再次加载
image2.display();
}
}
⚪适用性
-
远程代理(Remote Proxy)为一个对象在不同地址空间提供局部代表。
-
虚代理(Virtual Proxy)根据需要创建开销很大的对象。
- 保护代理 (Protection Proxy) 控制对原始对象的访问,用于对象应该有不同的访问权限的时候。
-
智能引用 (Smart Reference) 取代了简单的指针,它在访问对象时执行一些附加操作。典型用途包括:对指向实际对象的引用计数,这样当该对象没有引用时,可以被白动释放:当第一次引用一个持久对象时,将它装入内存:在访问一个实际对象前,检查是否已经锁定了它,以确保其他对象不能改变它。
⚪应用场景
- 远程代理:允许在不同地址空间中访问对象。例如,RMI(远程方法调用)中的远程代理允许客户端访问位于远程服务器上的对象。
- 虚拟代理:用于延迟加载,当创建对象开销很大时,可以通过虚拟代理在需要时才创建真实对象。例如,加载大型图像或文档时使用虚拟代理。
- 安全代理:用于控制对对象的访问权限,允许或拒绝请求。例如,访问敏感数据时的权限检查。
- 缓存代理:用于缓存对象,以提高性能。例如,在 Web 应用程序中缓存页面片段或数据库查询结果以减轻服务器负载。
- 日志记录:代理可以记录对象的访问日志,用于调试和分析。
- 动态代理:在运行时创建代理对象,通常用于实现 AOP(面向切面编程)等功能。
⚪实际已有场景
-
Hibernate 延迟加载:Hibernate 框架使用代理对象来实现延迟加载(Lazy Loading)策略。当访问对象属性时,Hibernate 可以使用代理对象来加载相关数据,而不是一次性加载整个对象图。
-
Spring 事务管理:Spring 的声明式事务管理是通过代理模式实现的。当方法被调用时,Spring 会使用代理对象来管理事务的开始、提交或回滚。
-
Spring Security:Spring Security 使用代理模式来控制访问权限。它可以包装目标对象并在方法执行前进行身份验证和权限检查。
-
Spring 缓存:Spring 提供了对缓存的支持,其中代理模式用于包装目标对象,并在方法调用前检查缓存以提高性能。
-
Spring AOP:Spring 使用代理模式来实现切面编程。通过代理,Spring 能够在方法执行前后织入切面逻辑,如日志、事务、性能监控等。