package proxy; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * @author jiq * 类型:Structural * 定义: 代理模式为另一个对象提供一个占位符(替身)以控制这个对象的访问。 * 话句话说,使用代理对象,可以让代理对象控制对某个对象的访问,被代理 * 的对象可以是远程对象,创建开销大的对象,或需要安全控制的对象。 * * 为什么要控制访问:代理模式之所以要控制访问,是因为我们的客户不知道如何同 * 远程对象(被代理的对象)沟通。 比如远程代理访问,其帮助我们处理一些网络 * 上的细节。 * * 区别: 装饰器模式包装一个对象,并提供额外的行为。 * 适配器模式包装一个对象,并转换成不同的接口(接口改变)。 * 外观模式包装许多对象,以简化他们的接口(接口改变)。 * 代理模式包装一个对象,并控制它的访问(不改变被代理对象的接口)。 * 其实虽然从结构上来看和Decorator模式类似,但Proxy是控制,更像是一种对功能的限制, * 而Decorator是增加职责。 * * 应用: Spring AOP的核心设计思想。 Java RMI(远程方法调用) * * 代码说明:由于一些特殊原因,客户端无法直接访问真正的主题(比如网络问题,并发换环境等)。 * 这个时候我们通过一个代理来控制对真正主题的访问,比如远程代理会帮忙处理一些网络上 * 的细节,多线程环境下的代理会帮忙解决一些同步问题等。 然后客户端通过代理来访问对象。 */ interface Subject{ public void request(); } /** * 真正的角色,实现了request方法 * */ class RealSubject implements Subject{ public void request(){ System.out.print("real request handling\n"); } } /************************************************ * 静态代理,封装(控制)request方法的访问 ************************************************/ class StaticProxySubject implements Subject{ private RealSubject realSubject; //组合被代理的对象 public void request(){ //do some thing else... if(realSubject == null){ realSubject = new RealSubject(); } realSubject.request(); //真正的request调用 //do some thing else... } } /*********************************************************** * 动态代理. java.lang.reflect包中有自己的代理支持,利用这个包 * 你可以在运行时动态创建一个代理类,实现一个或者多个接口,并将 * 方法的调用转发到你所指定的类。 * 因为实际的代理类是在运行时创建的,所以我们称这个技术为动态代理。 * ***********************************************************/ class DynamicProxySubject implements InvocationHandler{ private Object realSubject; //组合被代理的对象 public DynamicProxySubject(Object realSubject){ this.realSubject = realSubject; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //do some thing else... return method.invoke(realSubject, args); //do some thing else... } } /************************************************** * 客户端,代理ProxySubject控制其对RealSubject的访问 * ************************************************/ public class ProxyTest { public static void main(String[] args) { //通过静态代理来访问对象 Subject proxy = new StaticProxySubject(); proxy.request(); //通过动态代理来访问对象 RealSubject real = new RealSubject(); Subject subject = (Subject) Proxy.newProxyInstance( real.getClass().getClassLoader(), //定义代理类的类加载器 real.getClass().getInterfaces(), //代理类要实现的接口列表 new DynamicProxySubject(real)); //指派方法调用的调用处理程序 subject.request(); } }