1. 说明
- 1.代理模式(Proxy Pattern)。
- 2.意图:为其他对象提供一种代理以控制对这个对象的访问。
- 3.通过提供与对象相同的接口来控制对这个对象的访问。
- 4.是设计模式中的一种结构型模式。
- 5.创建了一个代表其他对象的代理对象,从而可以在不修改原始对象的基础上控制访问和附加操作。
2. 应用场景
- 1.远程代理(Remote Proxy):为一个位于不同的地址空间的对象提供一个本地的代理对象,这个不同的地址空间可以是同一台主机中的不同程序,也可以是网络上的不同主机。
- 2.虚拟代理(Virtual Proxy):根据需要创建开销很大的对象。通过它来存放实例化需要很长时间的真实对象。
- 3.保护代理(Protect or Access Control Proxy):控制对原始对象的访问。
- 4.智能引用(Smart Reference Proxy):当访问一个对象时,代理可以自动地处理一些附加操作,如:访问统计、安全检查等。
3. 结构图
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/7b1ba6e21b0e42e28f9fec4917d5eba9.png)
4. 构成
- 1.代理(Proxy)角色:保存一个引用使得代理可以访问实体;提供一个与 Subiect 的接口相同的接口,使代理可以用来代替实体;控制对实体的存取,并可能负责创建和删除它;其他功能依赖于代理的类型:Remote Proxy负责对请求及其参数进行编码,并向不同地址空间中的实体发送已编码的请求;Virtual Proxy 可以缓存实体的附加信息,以便延迟对它的访问;Protection Proxy 检查调用者是否具有实现一个请求所必需的访问权限。持有一个真实对象的引用,负责代理真实对象,并在真实对象处理前或处理后进行附加操作。
- 2.抽象主题(Subject)角色:定义 RealSubject 和 Proxy 的共用接口,这样就在任何使用 RealSubject 的地方都可以使用 Proxy。
- 3.真实主题(Real Subject)角色:定义 Proxy 所代表的实体。
5. 适用性
- 1.Proxy 模式适用于在需要比较通用和复杂的对象指针代替简单的指针的时候。
- 2.远程代理(Remote Proxy):为一个对象在不同地址空间提供局部代表。
- 3.虚代理(Virtual Proxy):根据需要创建开销很大的对象。
- 4.保护代理(Protection Proxy):控制对原始对象的访问,用于对象应该有不同的访问权限的时候。
- 5.智能引用(Smart Reference):取代了简单的指针,它在访问对象时执行一些附加操作。典型用途包括:对指向实际对象的引用计数,这样当该对象没有引用时,可以被自动释放;当第一次引用一个持久对象时,将它装入内存;在访问一个实际对象前,检查是否已经锁定了它,以确保其他对象不能改变它。
6. 优点
- 1.职责清晰:真实对象只关注业务逻辑,代理对象只关注非业务逻辑。
- 2.高扩展性:可以在不修改真实对象的前提下扩展功能。
- 3.智能化:代理对象可以在客户端和目标对象之间起到中介的作用,并且可以通过代理对象对目标对象进行封装和控制。
7. 缺点
- 1.代理类和委托类实现相同的接口,增加了额外的编程工作量和复杂性。
- 2.对于静态代理,如果接口增加方法,则代理类和目标类都需要进行修改,增加了代码的维护成本。
8. java示例
package com.learning.proxy;
/**
* 抽象主题角色
*/
interface TicketSubject {
void buyTicket(String userId);
}
package com.learning.proxy;
/**
* 真实主题角色
*/
class RealTicketSubject implements TicketSubject {
@Override
public void buyTicket(String userId) {
System.out.println("用户:" + userId + "买票中");
}
}
package com.learning.proxy;
/**
* 代理模式:代理类
*/
public class ProxyTicket implements TicketSubject {
private RealTicketSubject realTicketSubject;
public ProxyTicket(RealTicketSubject realTicketSubject) {
this.realTicketSubject = realTicketSubject;
}
@Override
public void buyTicket(String userId) {
// 前置条件检查,例如验证用户权限
if (!isUserAuthorized(userId)) {
System.out.println("用户"+userId+"无购票权限");
return;
}
// 记录日志
System.out.println("用户" + userId + "准备买票");
// 调用真实票务服务购票
realTicketSubject.buyTicket(userId);
// 记录日志
System.out.println("用户" + userId + "买票成功");
// 购票后的处理,如发送通知等
sendPurchaseNotification(userId);
}
private boolean isUserAuthorized(String userId) {
return userId.startsWith("VIP");
}
private void sendPurchaseNotification(String userId) {
System.out.println("用户" + userId+"已购票成功");
}
}
package com.learning.proxy;
public class Client {
public static void main(String[] args) {
RealTicketSubject realTicketSubject = new RealTicketSubject();
ProxyTicket proxyTicket = new ProxyTicket(realTicketSubject);
// 模拟用户购票
proxyTicket.buyTicket("VIP123");
proxyTicket.buyTicket("NORMAL456");
}
}
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/5ca583bdc0064ab58c5f2e147e825351.png)