- 代理模式
- 意图:为其他对象提供一种代理以控制对这个对象的访问。
- 例子:远程代理(访问远程对象)、虚拟代理(延迟加载大图片)、保护代理(控制权限)。


java
// 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("正在从远程服务器加载图片: " + filename);
// 模拟网络延迟
try { Thread.sleep(1000); }
catch (InterruptedException e) { e.printStackTrace(); }
}
@Override
public void display() {
System.out.println("显示图片: " + filename);
}
}
// 3. 虚拟代理(延迟加载代理)
class ImageProxy implements Image {
private String filename;
private RealImage realImage;
public ImageProxy(String filename) {
this.filename = filename;
}
@Override
public void display() {
// 延迟初始化:第一次调用时才创建真实对象
if (realImage == null) {
realImage = new RealImage(filename);
}
realImage.display();
}
}
// 4. 保护代理示例
interface SensitiveData {
void access();
}
class RealData implements SensitiveData {
private String data;
public RealData(String data) {
this.data = data;
}
@Override
public void access() {
System.out.println("访问敏感数据: " + data);
}
}
class ProtectionProxy implements SensitiveData {
private RealData realData;
private String userRole;
public ProtectionProxy(String data, String userRole) {
this.realData = new RealData(data);
this.userRole = userRole;
}
@Override
public void access() {
// 根据用户角色控制访问权限
if ("admin".equals(userRole)) {
realData.access();
} else {
System.out.println("拒绝访问:权限不足");
}
}
}
// 演示类
public class ProxyPatternDemo {
public static void main(String[] args) {
System.out.println("=== 虚拟代理演示(延迟加载)===");
Image image1 = new ImageProxy("photo1.jpg");
Image image2 = new ImageProxy("photo2.jpg");
System.out.println("代理对象已创建,但真实图片未加载");
System.out.println("首次调用display()时才会加载真实图片:");
image1.display(); // 此时才加载真实图片
System.out.println("\n=== 保护代理演示 ===");
SensitiveData data1 = new ProtectionProxy("机密数据", "user");
SensitiveData data2 = new ProtectionProxy("机密数据", "admin");
data1.access(); // 普通用户被拒绝
data2.access(); // 管理员可访问
System.out.println("\n=== 远程代理演示 ===");
Image remoteImage = new ImageProxy("remote_image.jpg");
System.out.println("远程代理已创建");
remoteImage.display(); // 模拟远程加载过程
}
}
运行结果:
复制代码
=== 虚拟代理演示(延迟加载)===
代理对象已创建,但真实图片未加载
首次调用display()时才会加载真实图片:
正在从远程服务器加载图片: photo1.jpg
显示图片: photo1.jpg
=== 保护代理演示 ===
拒绝访问:权限不足
访问敏感数据: 机密数据
=== 远程代理演示 ===
远程代理已创建
正在从远程服务器加载图片: remote_image.jpg
显示图片: remote_image.jpg
模式要点说明:
-
虚拟代理:
- 延迟创建开销大的对象(如大图片)
- 第一次访问时才初始化真实对象
- 优化性能,避免不必要的资源占用
-
远程代理:
- 隐藏远程对象的存在
- 处理网络通信细节(示例中简化了网络操作)
- 让客户端像使用本地对象一样使用远程对象
-
保护代理:
- 控制对敏感对象的访问
- 在代理中添加权限检查逻辑
- 真实对象无需关心权限验证
代理模式优势:
- 职责分离:代理对象可以处理附加逻辑(如权限、缓存、日志)
- 开闭原则:可以在不修改真实对象的情况下增加功能
- 控制访问:提供更精细的对象访问控制
这个示例展示了代理模式在不同场景下的灵活应用,实际开发中还可以结合动态代理实现更通用的代理逻辑。