代理模式(Proxy Pattern)
·
一、概念与定义
代理模式(Proxy Pattern) 是一种结构型设计模式,它通过一个代理对象来控制对另一个对象(目标对象)的访问。代理模式的核心思想是“间接访问”,即客户端不直接访问目标对象,而是通过代理对象间接访问。
二、基本结构
代理模式由以下四个角色组成:
| 角色 | 描述 |
|---|---|
| 抽象主题:Subject | 定义目标对象和代理的公共接口(如业务方法)。 |
| 真实主题:RealSubject | 实际目标对象,实现具体的业务逻辑。 |
| 代理主题:Proxy | 代理类,持有目标对象引用,控制对其的访问并添加额外的功能。 |
| 客户端:Client | 使用代理主题或真实主题的代码。 |
-
抽象主题(Subject)
- 定义目标对象和代理对象的共同接口,使得客户端无法区分目标对象和代理对象。
-
真实主题(Real Subject)
- 实际实现业务逻辑的对象,代理模式的主要目标是控制对它的访问。
-
代理主题(Proxy)
- 代理类,负责控制对真实主题的访问,并可以添加额外的功能(如日志记录、权限验证等)。
-
客户端(Client)
- 使用代理主题或真实主题的代码。
三、代理模式的类型
代理模式可以分为以下几种常见的类型:
-
远程代理(Remote Proxy)
- 用于隐藏远程对象的物理位置,使得客户端可以像操作本地对象一样操作远程对象。
-
虚拟代理(Virtual Proxy)
- 用于优化性能,延迟加载资源(如图片、视频等)。
-
保护代理(Protection Proxy)
- 用于控制对真实主题的访问权限,根据客户端的权限决定是否允许访问。
-
智能代理(Smart Proxy)
- 在访问真实主题时,自动添加额外的功能,如日志记录、缓存、计数器等。
四、生活场景类比
外卖配送场景
- 真实主题(Real Subject):外卖骑手,负责实际送餐。
- 代理主题(Proxy):外卖平台,接收订单并分配给骑手。
- 客户端(Client):用户通过外卖平台下单,而不是直接联系骑手。
流程:
- 用户通过外卖平台下单。
- 外卖平台(代理)接收订单并分配给骑手(真实主题)。
- 骑手完成送餐任务。
通过代理模式,用户无需直接与骑手打交道,而是通过平台完成整个流程,从而简化了操作。
五、Java代码示例
1. 完整代码结构
(1)抽象主题(Subject)
//Subject接口:定义订单处理规范
interface DeliveryService {
// 调用骑手送餐
void placeOrder(String orderId, String address);
}
(2)真实主题(Real Subject)
//RealSubject:骑手(真实送餐对象)
class Rider implements DeliveryService {
@Override
public void placeOrder(String orderId, String address) {
System.out.println("[骑手] 订单号 " + orderId + " 已接单,送往地址: " + address);
deliverFood(orderId);
}
private void deliverFood(String orderId) {
System.out.println("[骑手] 配送中... 订单号: " + orderId);
System.out.println("[骑手] 订单号 " + orderId + " 已完成配送!");
}
}
(3)代理主题(Proxy)
//Proxy:外卖平台(代理订单分配与验证)
class FoodDeliveryPlatform implements DeliveryService {
private Rider rider; // 持有真实骑手对象
private boolean isOrderValid(String orderId) {
// 模拟订单验证逻辑(如校验地址、支付状态等)
return !orderId.isEmpty();
}
@Override
public void placeOrder(String orderId, String address) {
System.out.println("[平台] 接收到订单: " + orderId + ",地址: " + address);
// 代理附加逻辑:订单校验
if (!isOrderValid(orderId)) {
System.out.println("[平台] 错误!订单号无效,配送终止。");
return;
}
System.out.println("[平台] 订单校验通过,分配骑手中...");
// 延迟初始化骑手(模拟资源优化)
if (rider == null) {
rider = new Rider();
}
// 调用真实骑手送餐
rider.placeOrder(orderId, address);
// 代理附加逻辑:记录日志
System.out.println("[平台] 订单号 " + orderId + " 配送流程已记录。");
}
}
(4)客户端(ClientApp)
//4. 客户端(用户下单)
public class ClientApp {
public static void main(String[] args) {
// 用户直接与外卖平台(代理)交互
DeliveryService platform = new FoodDeliveryPlatform();
// 正常订单
platform.placeOrder("ORDER_202502241001", "北京市朝阳区");
System.out.println("---------------");
// 无效订单(空订单号)
platform.placeOrder("", "上海市浦东新区");
}
}
运行结果
[平台] 接收到订单: ORDER_202502241001,地址: 北京市朝阳区
[平台] 订单校验通过,分配骑手中...
[骑手] 订单号 ORDER_202502241001 已接单,送往地址: 北京市朝阳区
[骑手] 配送中... 订单号: ORDER_202502241001
[骑手] 订单号 ORDER_202502241001 已完成配送!
[平台] 订单号 ORDER_202502241001 配送流程已记录。
---------------
[平台] 接收到订单: ,地址: 上海市浦东新区
[平台] 错误!订单号无效,配送终止。
六、代理模式的特点
-
透明性
- 客户端无法区分真实主题和代理主题,两者具有相同的接口。
-
间接访问
- 客户端通过代理间接访问真实主题。
-
额外功能
- 代理可以在不修改真实主题代码的情况下,为客户端添加额外的功能(如日志记录、权限验证等)。
-
灵活性
- 代理模式可以在不修改真实主题的情况下,灵活地扩展功能。
七、适用场景
-
远程访问
- 用于隐藏远程对象的物理位置,提供透明的访问方式。
-
延迟加载
- 用于优化性能,延迟加载资源(如图片、视频等)。
-
权限控制
- 用于控制对真实主题的访问权限,根据客户端的权限决定是否允许访问。
-
功能扩展
- 在不修改真实主题的情况下,通过代理添加额外的功能(如日志记录、缓存等)。
八、优缺点
优点
-
透明性
- 客户端无需修改代码即可使用代理。
-
灵活性
- 可以在不修改真实主题的情况下,灵活地扩展功能。
-
优化性能
- 通过延迟加载或缓存等技术优化系统性能。
-
控制访问
- 可以通过代理控制对真实主题的访问权限。
缺点
-
增加复杂性
- 引入代理类会增加系统的复杂性。
-
额外开销
- 代理模式可能会带来额外的性能开销(如方法调用的额外步骤)。
-
维护成本
- 需要维护代理类和真实主题类之间的同步。
九、总结
代理模式通过引入代理对象,间接地控制对真实主题的访问。它具有透明性、灵活性和扩展性等优点,适用于需要控制访问权限、优化性能或扩展功能的场景。在实际开发中,代理模式可以显著提高系统的灵活性和可维护性。
更多推荐



所有评论(0)