代理模式(Proxy Pattern)实现与对比
1. 虚拟代理(Virtual Proxy)
定义:延迟加载对象,避免资源浪费。
适用场景:大文件或资源的加载(如图片、数据库连接)。
代码示例
// 接口
interface Image {
void display();
}
// 真实对象(大文件)
class RealImage implements Image {
private String fileName;
public RealImage(String fileName) {
this.fileName = fileName;
loadFromDisk();
}
@Override
public void display() {
System.out.println("Displaying " + fileName);
}
private void loadFromDisk() {
System.out.println("Loading " + fileName + " from disk");
}
}
// 代理对象(延迟加载)
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 Main {
public static void main(String[] args) {
Image image = new ProxyImage("large_image.jpg");
// 第一次调用时加载
image.display();
// 第二次调用直接使用已加载对象
image.display();
}
}
注释说明:
ProxyImage
延迟加载RealImage
,避免初始化时加载大文件。- 第一次调用
display()
时触发加载,后续直接使用已加载对象。
2. 保护代理(Protection Proxy)
定义:控制对真实对象的访问权限。
适用场景:资源访问权限校验(如文件读写、API调用)。
代码示例
// 接口
interface Resource {
void writeData(String data);
}
// 真实资源(需权限控制)
class RealResource implements Resource {
@Override
public void writeData(String data) {
System.out.println("Writing data: " + data);
}
}
// 保护代理(权限校验)
class ProtectionProxy implements Resource {
private RealResource realResource;
private String user;
public ProtectionProxy(String user) {
this.user = user;
this.realResource = new RealResource();
}
@Override
public void writeData(String data) {
if (isAuthorized(user)) {
realResource.writeData(data);
} else {
System.out.println("Access denied for user: " + user);
}
}
private boolean isAuthorized(String user) {
// 模拟权限校验
return user.equals("admin");
}
}
// 使用示例
public class Main {
public static void main(String[] args) {
Resource proxyAdmin = new ProtectionProxy("admin");
proxyAdmin.writeData("Sensitive data"); // 允许
Resource proxyUser = new ProtectionProxy("user");
proxyUser.writeData("Sensitive data"); // 拒绝
}
}
注释说明:
ProtectionProxy
校验用户权限,只有admin
可以写入数据。- 通过
isAuthorized()
方法实现权限逻辑。
3. 智能代理(Smart Proxy)
定义:在访问对象时附加额外功能(如日志、计数、缓存)。
适用场景:AOP(日志、性能监控、事务管理)。
代码示例
// 接口
interface Service {
void execute();
}
// 真实服务
class RealService implements Service {
@Override
public void execute() {
System.out.println("Executing real service");
}
}
// 智能代理(添加日志和计数)
class SmartProxy implements Service {
private RealService realService;
private int callCount = 0;
public SmartProxy() {
this.realService = new RealService();
}
@Override
public void execute() {
System.out.println("Proxy: Logging before execution");
realService.execute();
callCount++;
System.out.println("Proxy: Call count = " + callCount);
}
}
// 使用示例
public class Main {
public static void main(String[] args) {
Service proxy = new SmartProxy();
proxy.execute();
proxy.execute();
}
}
注释说明:
SmartProxy
在调用execute()
前后添加日志,并记录调用次数。- 附加功能(日志、计数)与真实业务逻辑分离。
4. 远程代理(Remote Proxy)
定义:为远程对象提供本地访问接口。
适用场景:RPC(远程过程调用)或 Web Service。
代码示例(简化版)
// 远程服务接口
interface RemoteService {
String getData();
}
// 远程对象(模拟远程调用)
class RealRemoteService implements RemoteService {
@Override
public String getData() {
return "Data from remote server";
}
}
// 远程代理(包装网络调用)
class RemoteProxy implements RemoteService {
private RealRemoteService realService;
public RemoteProxy() {
// 模拟网络延迟
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.realService = new RealRemoteService();
}
@Override
public String getData() {
return realService.getData();
}
}
// 使用示例
public class Main {
public static void main(String[] args) {
RemoteService proxy = new RemoteProxy();
System.out.println(proxy.getData());
}
}
注释说明:
RemoteProxy
模拟远程调用的延迟和网络封装。- 客户端通过代理对象透明地访问远程服务。
对比表格
代理类型 | 定义 | 核心代码 | 使用场景 | 优点 | 缺点 |
---|---|---|---|---|---|
虚拟代理 | 延迟加载对象,节省资源。 | ProxyImage 延迟加载 RealImage 。 | 图片加载、大文件处理。 | 减少初始化开销,提升性能。 | 首次访问有延迟。 |
保护代理 | 控制对对象的访问权限。 | ProtectionProxy 校验用户权限。 | 文件/资源访问控制、API权限管理。 | 保护资源安全,防止未授权访问。 | 需维护权限校验逻辑。 |
智能代理 | 在访问对象时附加额外功能(日志、计数、缓存)。 | SmartProxy 记录调用次数并添加日志。 | AOP、性能监控、事务管理。 | 解耦横切关注点,增强功能透明化。 | 可能增加调用开销。 |
远程代理 | 为远程对象提供本地访问接口。 | RemoteProxy 模拟网络调用延迟。 | RPC、Web Service、分布式系统。 | 隐藏网络细节,简化客户端调用。 | 网络延迟和通信开销。 |
总结
-
选择代理类型依据:
- 虚拟代理:资源加载需延迟或节省内存时。
- 保护代理:需权限控制的资源访问。
- 智能代理:需附加功能(日志、监控)的场景。
- 远程代理:访问远程服务或分布式系统。
-
Spring中的应用:
- AOP代理:Spring AOP通过动态代理实现智能代理(如日志、事务)。
- 远程调用:Spring Remoting提供远程代理支持。
通过合理选择代理模式,可以提升代码的灵活性、安全性和性能,同时解耦对象的访问与实现。