代理模式:
为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
代理模式一般涉及到的角色有:
- 抽象角色:声明真实对象和代理对象的共同接口;
- 代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。
- 真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。
代理模式示例:
interface Subject
{
void request();
}
class RealSubject implements Subject
{
public void request()
{
System.out.println("From real subject.");
}
}
public class ProxySubject implements Subject
{
private Subject realSubject; // 以真实角色作为代理角色的属性
public ProxySubject(Subject subject)
{
realSubject = subject;
}
public void request() // 该方法封装了真实对象的request方法
{
preRequest();
System.out.println("From proxy, request.");
realSubject.request(); // 此处执行真实对象的request方法
postRequest();
}
private void preRequest()
{
System.out.println("From proxy, preRequest.");
}
private void postRequest()
{
System.out.println("From proxy, postRequest.");
}
public static void main(String []argv)
{
Subject realSubject = new RealSubject();
Subject proxySubject = new ProxySubject(realSubject);
proxySubject.request();
}
}
Java自身也支持代理模式:
package pattern.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyTest
{
/**
* @param args
*/
public static void main(String[] args) throws Throwable
{
Subject realSubjext = new RealSubject(); // 在这里指定被代理类
InvocationHandler handler = new MyHandler(realSubjext); // 初始化代理类
Subject proxySubject = (Subject) Proxy.newProxyInstance(Thread
.currentThread().getContextClassLoader(), realSubjext.getClass()
.getInterfaces(), handler);
proxySubject.request();
}
}
interface Subject
{
public final int i = 10;
void request();
}
class RealSubject implements Subject
{
public void request()
{
System.out.println("real subject called!");
}
}
class MyHandler implements InvocationHandler
{
private Subject target;
public MyHandler(Subject target)
{
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
System.out.println("proxy called. method is " + method.getName());
return method.invoke(target, args);
}
}
代理模式有如下主要应用:
- 远程代理:也就是为一个对象在不同的地址空间提供局部代表,这样可以隐藏一个对象存在于不同地址空间的事实。这个不同的地址空间可以是在本机器上,也可以在另一台机器中。
- 虚拟代理:是根据需要创建开销很大的对象,通过它来存放实例化需要很长时间的真实对象,使其只有在真正需要时才被创建。
- 安全代理:也叫保护代理,用来控制真实对象访问时的权限,如果有必要的话,可以给不同调用者提供不同的权限。
- 智能指引:是指当调用真实对象时,代理处理另外一些事,比如记录对此对象的调用次数等。
- 写时拷贝:虚拟代理的一种,把复制推迟到只有客户的需要时才进行。
- 缓存代理:为某一个目标的操作结果提供临时存储空间,以便其他客户的可以共享访问,有点缓存的味道。
- 防火墙代理:保护对象,不让用户访问,安全代理的特例。
- 同步代理:可以让几个用户同时访问同一个对象而不产生冲突。
常用的是前四种代理方式。
参考资料:
设计模式--代理模式
设计模式:代理模式和反射原理
Java设计模式圣经连载(05)-代理模式
常见设计模式之代理模式(Proxy)
java 反射和代理机制
设计模式(十一)代理模式Proxy(结构型)
http://www.iteye.com/problems/15304