定义
为其他对象提供一个代理,以控制对这个对象的访问。
类型
结构型模式
结构
代理模式由以下几部分组成:
抽象主题(Subject)
定义 RealSubjet 和 Proxy 的共用接口,这样就在任何使用 RealSubject 的地方可以使用 Proxy;
真实主题(RealSubject)
定义 Proxy 所代表的实体。
代理(Proxy):
- 保存一个引用使得代理可以访问实体;若 RealSubjet 和 Subject 接口相同,Proxy 会引用 Subject;
- 提供一个与 Subject 接口相同的接口,这样代理可以用它来代替实体;
- 控制对实体的存取,并可能负责创建和删除它;
- 其他功能依赖于代理的类型:
- 远程代理(Remote Proxy): 负责对请求及其参数进行编码,并向不同地址空间中的实体发送已编码的请求;
- 虚代理(Virtual Proxy): 可以缓存实体的附加信息,以便延迟对它的访问;
- 保护代理(Protection Proxy): 检查调用者是否具实现一个请求所必须的访问权限;
优点
- 协调调用者和被调用者,降低了系统的耦合度;
- 代理对象作为客户端和目标对象之间的中介,起到了保护目标对象的作用。
缺点
- 由于在客户端和真实主题之间增加了代理对象,因此会造成请求的处理速度变慢;
- 实现代理模式需要额外的工作,从而增加了系统实现的复杂度。
使用场景
以下情况适用 Proxy 模式:
- 远程代理 (Remote Proxy): 为一个对象在不同的地址空间提供局部代表。例如在分布式对象调用的场景,使用一个本地对象代理一个远程地址空间中的远程对象,对本地对象的方法调用可以引起远程对象中的方法调用;
- 虚代理 (Virtual Proxy): 根据需要创建开销很大的对象;
- 保护代理 (Protection Proxy): 控制对原始对象的访问。保护代理用于对象应该有不同的访问权限时;
- 智能指引 (Smart Reference): 取代简单指针,在访问对象时增加了一些附加操作。典型用途包括:(1) 对指向实际引用的对象计数,这样当该对象没有引用时可以自动释放;(2) 当第一次引用一个持久对象时,将它装入内存;(3) 在访问一个持久对象前,检查它是否已经锁定,以确保其他对象不能改变它。
代理模式实现
静态代理模式
静态代理模式代理和被代理对象在代理之前都是确定的,他们都实现相同的接口或者继承相同的抽象类。其结构对应上文所示类图。
抽象主题(Subject)
public interface Subject {
void execute();
}
真实主题(RealSubject)
public class RealSubject implements Subject {
@Override
public void execute() {
System.out.println("RealSubject execute...");
}
}
代理类(Proxy)
public class Proxy implements Subject {
private Subject subject;
public Proxy(Subject s) {
this.subject = s;
}
@Override
public void execute() {
this.subject.execute();
}
}
客户端(Client)
public class Client {
public static void main(String... args) {
new Client().test();
}
private void test() {
Subject subject = new CustomProxy(new RealSubject());
subject.execute();
}
}
动态代理模式
动态代理指动态的在内存中构建代理对象。
在 Java 中,通过使用反射技术,一个代理类可以为任意类提供代理,代理类必须实现 InvocationHandler
接口。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的代理程序的 invoke
方法。invoke
方法运用反射技术,通过 java.lang.reflect.Proxy
类中提供的静态方法 newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序,也就是代理类实现的 InvocationHandler
接口中的 invoke
方法中。
抽象主题(Subject)
public interface Subject {
void execute();
}
真实主题(RealSubject)
public class RealSubject implements Subject {
@Override
public void execute() {
System.out.println("RealSubject execute...");
}
}
代理类(Proxy)
public class CustomProxy implements InvocationHandler {
private Object object;
public CustomProxy(Object obj) {
this.object = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("proxy execute start");
Object resultObject = method.invoke(object, args);
System.out.println("proxy execute end");
return resultObject;
}
}
客户端(Client)
public class Client {
public static void main(String[] args) {
new Client().test();
}
private void test() {
Subject subject = new RealSubject();
CustomProxy customProxy = new CustomProxy(subject);
subject = (Subject) Proxy.newProxyInstance(Client.class.getClassLoader(), subject.getClass().getInterfaces(),
customProxy);
subject.execute();
}
}
参考代码
https://github.com/xueyufish/design-pattern/tree/master/proxy