代理模式 (Proxy Pattern)
代码示例:
git clone https://gitee.com/qq1244811434/23DesignPatterns.git
优点
- 增加系统复杂度
- 可能影响系统性能
缺点
- 增加系统复杂度
- 可能影响系统性能
特点
- 控制对象访问,增强安全性
- 支持延迟加载、缓存等功能
- 降低系统耦合度
应用场景
- 远程代理
- 图像加载
- 网络访问控制
分类
-
虚拟代理模式(延迟加载)
/** * 真实图像类 */ public static class RealImage implements Image { private String fileName; public RealImage(String fileName) { this.fileName = fileName; loadFromDisk(fileName); } @Override public void display() { System.out.println("显示图像: " + fileName); } private void loadFromDisk(String fileName) { System.out.println("从磁盘加载图像: " + fileName); } } /** * 代理图像类 - 虚拟代理(延迟加载) */ public static 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 static class RealInternet implements Internet { @Override public void connectTo(String serverHost) { System.out.println("连接到服务器: " + serverHost); } } /** * 代理网络类 - 保护代理(访问控制) */ public static class ProxyInternet implements Internet { private Internet internet = new RealInternet(); private static final String[] bannedSites = {"abc.com", "def.com", "ghi.com"}; @Override public void connectTo(String serverHost) { if (isBanned(serverHost)) { System.out.println("访问被拒绝: " + serverHost); } else { internet.connectTo(serverHost); } } private boolean isBanned(String serverHost) { for (String bannedSite : bannedSites) { if (serverHost.equals(bannedSite)) { return true; } } return false; } } -
缓存代理模式
/** * 数据库接口 */ public interface Database { String query(String sql); } /** * 真实数据库类 */ public static class RealDatabase implements Database { @Override public String query(String sql) { System.out.println("执行SQL查询: " + sql); return "查询结果: " + sql; } } /** * 缓存代理类 */ public static class CachedDatabase implements Database { private RealDatabase realDatabase = new RealDatabase(); private java.util.Map<String, String> cache = new java.util.HashMap<>(); @Override public String query(String sql) { if (cache.containsKey(sql)) { System.out.println("从缓存获取结果: " + sql); return cache.get(sql); } else { String result = realDatabase.query(sql); cache.put(sql, result); System.out.println("结果已缓存: " + sql); return result; } } }
测试
/**
* 演示代理模式
*/
@GetMapping("/proxy")
public Map<String, Object> demonstrateProxy() {
Map<String, Object> result = new HashMap<>();
result.put("pattern", "代理模式");
result.put("description", "为其他对象提供一种代理以控制对这个对象的访问");
// 执行代理模式演示
proxyPattern.demonstrateProxyPattern();
result.put("message", "代理模式演示完成,请查看控制台输出");
return result;
}
输出结果:
{
"pattern": "代理模式",
"description": "为其他对象提供一种代理以控制对这个对象的访问",
"message": "代理模式演示完成,请查看控制台输出"
}
控制台输出内容:
=== 虚拟代理模式演示(延迟加载)===
第一次调用display():
从磁盘加载图像: test.jpg
显示图像: test.jpg
第二次调用display():
显示图像: test.jpg
=== 保护代理模式演示(访问控制)===
连接到服务器: google.com
访问被拒绝: abc.com
连接到服务器: github.com
访问被拒绝: def.com
=== 缓存代理模式演示 ===
执行SQL查询: SELECT * FROM users
结果已缓存: SELECT * FROM users
查询结果: SELECT * FROM users
从缓存获取结果: SELECT * FROM users
查询结果: SELECT * FROM users
执行SQL查询: SELECT * FROM orders
结果已缓存: SELECT * FROM orders
查询结果: SELECT * FROM orders
完整代码
package com.example.patterns.proxy;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
* 代理模式演示
*
* 代理模式为其他对象提供一种代理以控制对这个对象的访问。
* 代理模式在访问对象时引入一定程度的间接性,可以用于控制访问、延迟加载、缓存等。
*
* 应用场景:
* - 远程代理
* - 虚拟代理(延迟加载)
* - 保护代理(访问控制)
* - 缓存代理
*/
@Component
public class ProxyPattern {
/**
* 图像接口
*/
public interface Image {
void display();
}
/**
* 真实图像类
*/
public static class RealImage implements Image {
private String fileName;
public RealImage(String fileName) {
this.fileName = fileName;
loadFromDisk(fileName);
}
@Override
public void display() {
System.out.println("显示图像: " + fileName);
}
private void loadFromDisk(String fileName) {
System.out.println("从磁盘加载图像: " + fileName);
}
}
/**
* 代理图像类 - 虚拟代理(延迟加载)
*/
public static 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 interface Internet {
void connectTo(String serverHost);
}
/**
* 真实网络类
*/
public static class RealInternet implements Internet {
@Override
public void connectTo(String serverHost) {
System.out.println("连接到服务器: " + serverHost);
}
}
/**
* 代理网络类 - 保护代理(访问控制)
*/
public static class ProxyInternet implements Internet {
private Internet internet = new RealInternet();
private static final String[] bannedSites = {"abc.com", "def.com", "ghi.com"};
@Override
public void connectTo(String serverHost) {
if (isBanned(serverHost)) {
System.out.println("访问被拒绝: " + serverHost);
} else {
internet.connectTo(serverHost);
}
}
private boolean isBanned(String serverHost) {
for (String bannedSite : bannedSites) {
if (serverHost.equals(bannedSite)) {
return true;
}
}
return false;
}
}
/**
* 数据库接口
*/
public interface Database {
String query(String sql);
}
/**
* 真实数据库类
*/
public static class RealDatabase implements Database {
@Override
public String query(String sql) {
System.out.println("执行SQL查询: " + sql);
return "查询结果: " + sql;
}
}
/**
* 缓存代理类
*/
public static class CachedDatabase implements Database {
private RealDatabase realDatabase = new RealDatabase();
private Map<String, String> cache = new HashMap<>();
@Override
public String query(String sql) {
if (cache.containsKey(sql)) {
System.out.println("从缓存获取结果: " + sql);
return cache.get(sql);
} else {
String result = realDatabase.query(sql);
cache.put(sql, result);
System.out.println("结果已缓存: " + sql);
return result;
}
}
}
/**
* 演示代理模式的使用
*/
public void demonstrateProxyPattern() {
System.out.println("=== 虚拟代理模式演示(延迟加载)===");
Image image = new ProxyImage("test.jpg");
// 第一次调用时才会加载图像
System.out.println("第一次调用display():");
image.display();
// 第二次调用时直接显示,不会重新加载
System.out.println("第二次调用display():");
image.display();
System.out.println("\n=== 保护代理模式演示(访问控制)===");
Internet internet = new ProxyInternet();
internet.connectTo("google.com");
internet.connectTo("abc.com"); // 被禁止的网站
internet.connectTo("github.com");
internet.connectTo("def.com"); // 被禁止的网站
System.out.println("\n=== 缓存代理模式演示 ===");
Database database = new CachedDatabase();
// 第一次查询,会执行真实查询
System.out.println(database.query("SELECT * FROM users"));
// 第二次查询相同SQL,从缓存获取
System.out.println(database.query("SELECT * FROM users"));
// 查询不同的SQL
System.out.println(database.query("SELECT * FROM orders"));
}
}
UML:

代理模式与装饰器模式的区别
-
装饰器模式关注于在对象上动态添加新行为,而代理模式虽然也可以增加新的行为,但关注于控制对象的访问。
-
装饰器模式执行主体是原类;代理模式是代理原类进行操作,执行主体是代理类。
-
代理模式中,代理类可以对客户端隐藏真实对象的具体信息,因此使用代理模式时,我们常常在代理类中创建真实对象的实例。而装饰器模式的通常做法是将原始对象作为参数传给装饰者的构造器。也就是说。代理模式的代理和真实对象之间的对象通常在编译时就已经确定了,而装饰者能够在运行时递归地被构造。

2万+

被折叠的 条评论
为什么被折叠?



