Java适配器模式、代理模式及动态代理

来源:互联网 发布:淘宝冰点营销怎么使用 编辑:程序博客网 时间:2024/06/05 01:14

       适配器模式和代理模式表面上看来都是通过添加中间层来解除紧耦合的问题,那么这两种模式有什么区别呢,刚学不久的人真心会感到混乱。

       适配器模式主要解决的是接口的兼容性问题,比如有A、B两个接口,在客户端,应用程序主要使用的是A接口提供的服务,在使用的过程中,发现B接口和A接口提供的服务具有相似性,因此我想在不改动我应用程序的基础上也能获取B接口的服务。怎么办呢,如果对B接口(及实现它的子类)进行重构,工作量太大,那么就引入一个适配器C,C实现A接口,C的内部包含B接口的实例,这样就可以通过包含的B接口实例来完成A接口所需提供的功能。注意,适配器模式下,C中可能不需要B接口提供的所有的服务,部分就可以了。

       再看代理模式,它主要是针对不方便把接口的实现暴露给客户端,或者需要除了原始服务之外,还要添加一些额外的功能,如添加日志,缓存等,从而引入一个中间的代理,由代理直接与客户端对话。代理内部同样包含被代理接口的实例,但是一般代理提供的服务包含被代理接口所能提供的所有服务。

   

            关于动态代理:利用java提供的反射机制,可以进一步实现动态代理。静态代理都是通过添加附加的代理类来实现,当接口数量较多时,编码量会比较大,并且由于增加了代理类,导致系统结构比较臃肿。能不能在运行时动态地生成代理呢?

       JDK提供了实现动态代理的方法(除此以外,还有cglib也能生成动态代理),利用java.lang.reflect.* 中的InvocationHandler,Proxy可以实现动态代理。JDK实现动态代理的核心是,利用Proxy类提供的静态方法newProxyInstance得到动态代理类。需要提供三个参数:被代理类的ClassLoader类,被代理类实现的所有接口(以Class[],数组的形式),还有InvocationHandler接口的一个实现。InvocationHandler的实现负责所有代理对象上的方法调用,也就是对代理对象上的方法调用,都会交给传入的InvocationHandler实例,通过invoke方法去处理。


        实例代码:

<pre name="code" class="java">package reflection;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;class DynamicProxyHandler implements InvocationHandler{private Object proxied;public DynamicProxyHandler(Object proxied) {// TODO Auto-generated constructor stubthis.proxied = proxied;}public Object invoke(Object proxy, Method method, Object[] args)throws Throwable{System.out.println("proxy: " + proxy.getClass() + ", method: " + method);return method.invoke(proxied, args);}}public class DynamicProxy {public static void consumer(Interface iface){iface.doSomething();iface.somethingElse("bonobo");}public static void main(String[] args) {RealObject real = new RealObject();consumer(real);Interface proxy = (Interface)Proxy.newProxyInstance(Interface.class.getClassLoader(), new Class[]{Interface.class}, new DynamicProxyHandler(real));consumer(proxy);}}


其中,Interface是预先定义的接口:

package reflection;interface Interface{void doSomething();void somethingElse(String arg);}class RealObject implements Interface{public void doSomething(){System.out.println("doSomething");}public void somethingElse(String arg){System.out.println("somethingElse "+arg);}}
代码摘自:Thinking in Java


另外,这篇文章:http://blog.csdn.net/luanlouis/article/details/24589193。

从.class文件到内存中Class对象的生成,讲述了动态创建类的原理,然后再讲了两种实现动态代理的方式,指出JDK动态代理的缺陷是不能代理不属于接口中声明的方法乃至没有实现接口的类,采用cglib则可以很好地解决

另外,文章中多出使用的jd-gui反编译工具也很有意思。

0 0