代理模式
目的
为其他对象提供一种代理以控制对这个对象的访问。
介绍
代理有四类:
- 远程代理(Remote Proxy): 控制对远程对象(不同地址空间)的访问,负责将请求及其参数进行编码,并向不同地址空间中的对象发送已经编码的请求。
- 虚拟代理(Virtual Proxy): 根据需要创建开销很大的对象,可以缓存实体的附加信息,以便延迟对它的访问,例如在网站加载一个很大图片时,不能马上完成,可以用虚拟代理缓存图片的大小信息,然后生成一张临时图片代替原始图片。
- 保护代理(Protection Proxy): 按权限控制对象的访问,负责检查调用者是否具有实现一个请求所必须的访问权限。
- 智能代理(Smart Reference): 取代了简单的指针,它在访问对象时执行一些附加操作: 记录对象的引用次数;当第一次引用一个持久化对象时,将它装入内存;在访问一个实际对象前,检查是否已经锁定了它,以确保其它对象不能改变它。
类图
角色
- Subject: 抽象主题角色
- Proxy: 代理主题角色
- RealSubject: 真实主题角色
实现
抽象主题
public interface Subject {
void doOperation();
}
真实主题角色
public class RealSubject implements Subject {
private String name;
public RealSubject(String name){
this.name = name;
loadFromDisk(fileName);
}
@Override
public void doOperation() {
System.out.println("doOperation" + name);
}
private void custom(String name){
System.out.println("Loading " + name);
}
}
代理主题角色
public class ProxySubject implements Subject{
private RealSubject realSubject;
private String name;
public ProxySubject(String name){
this.name = name;
}
@Override
public void doOperation() {
if(realSubject == null){
realSubject = new RealSubject(name);
}
realSubject.doOperation();
}
}
调用类
public class ProxyPatternDemo {
public static void main(String[] args) {
Subject subject = new ProxySubject("proxyName");
subject.doOperation();
...
}
}
优缺点
优点
- 能够协调调用者和被调用者,在一定程度上降低了系统的耦合度。
- 远程代理使客户端可以访问在远程机器上的对象,可以快速响应并处理客户端请求。
- 虚拟代理通过使用一个小对象来代表一个大对象,减少系统资源的消耗。
- 保护代理可以控制对真实对象的使用权限。
缺点
- 客户端和真实主题之间增加了代理对象,可能会造成处理速度变慢。
- 有些代理模式的实现非常复杂。
使用场景
- 远程(Remote)代理:为一个位于不同的地址空间的对象提供一个本地 的代理对象,这个不同的地址空间可以是在同一台主机中,也可是在另一台主机中,远程代理又叫做大使(Ambassador)。
- 虚拟(Virtual)代理:如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建。
- Copy-on-Write代理:它是虚拟代理的一种,把复制(克隆)操作延迟 到只有在客户端真正需要时才执行。一般来说,对象的深克隆是一个 开销较大的操作,Copy-on-Write代理可以让这个操作延迟,只有对象被用到的时候才被克隆。
- 保护(Protect or Access)代理:控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限。
- 缓冲(Cache)代理:为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。
- 防火墙(Firewall)代理:保护目标不让恶意用户接近。
- 同步化(Synchronization)代理:使几个用户能够同时使用一个对象而没有冲突。
- 智能引用(Smart Reference)代理:当一个对象被引用时,提供一些额外的操作,如将此对象被调用的次数记录下来等。
使用
- java.lang.reflect.Proxy
- RMI