深度解析Java静态代理与动态代理模式的实现( 二 )

2.2.4:我们的文档编辑器现在要开始进行文档编辑了,我们来实现具体的代码,我们先来引用一下原对象,看一下原来的对象会出现什么情况:
public class DocumentEditor {public static void main(String[] args) {Graphic proxy = new Image();//引用代码proxy.load();proxy.Draw();proxy.GetExtent();proxy.Store();}}2.2.5:测试代码
正在创建对象进行加载..进行绘画..获取图片的属性是:Extent [width=100, length=200]图片进行存储在硬盘里..我们可以看出,它会消耗3秒才会出来具体的对象,并且没有我们所需要的记录 。好了,我们把2.2.4的引用代码改为: Graphic proxy = new ImageProxy();
我们再来测试一下:
正在创建对象---第一步开始---进行加载..---第一步结束------第二步开始---进行绘画..---第二步结束------第三步开始---获取图片的属性是:Extent [width=100, length=200]---第三步结束-----第四步开始---图片进行存储在硬盘里..---第四步结束--很明显可以看出,通过访问我们的代理对象,就可以实现对原方法的改造,这就是代理模式的精髓思想 。不过到这里你可能会问,为什么不对原对象进行改造呢?为什么要给他新建一个代理对象,这不是很麻烦吗 。回答这个问题,首先要提一个代码的设计原则,也就是有名的开闭原则:对扩展开放,对修改关闭 。这句话的意思就是不建议对原有的代码进行修改,我们要做的事就是尽量不用动原有的类和对象,在它的基础上去改造,而不是直接去修改它 。至于这个原则为什么这样,我想其中一个原因就是因为软件体系中牵一发很动全身的事情很常见,很可能你修改了这一小块,然而与此相关的很多东西就会发生变化 。所以轻易不要修改,而是扩展 。
三:实现动态代理
3.1:静态代理的不足:
通过看静态代理可以动态扩展我们的对象,但是有个问题,在我们进行方法扩展的时候,比如我们的日志功能:每个前面都得写第一步、第二步 。如果我们要再一些其他的东西,比如权限校验、代码说明,一个两个方法还好,万一方法成百个呢,那我们岂不是要累死 。这就是动态代理要解决的问题,只需要写一次就可以,究竟是怎么实现的呢,接下里我们来一探究竟吧 。
3.2:动态代理的准备:
动态代理需要用到JDk的Proxy类,通过它的newProxyInstance()方法可以生成一个代理类,我们来通过jdk看一下具体的说明,如何使用它:
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)throws IllegalArgumentException返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序 。此方法相当于:
Proxy.getProxyClass(loader, interfaces).getConstructor(new Class[] { InvocationHandler.class }).newInstance(new Object[] { handler }); Proxy.newProxyInstance 抛出 IllegalArgumentException,原因与 Proxy.getProxyClass 相同 。
参数:loader - 定义代理类的类加载器interfaces - 代理类要实现的接口列表h - 指派方法调用的调用处理程序返回:一个带有代理类的指定调用处理程序的代理实例,它由指定的类加载器定义,并实现指定的接口抛出:IllegalArgumentException - 如果违反传递到 getProxyClass 的参数上的任何限制NullPointerException - 如果 interfaces 数组参数或其任何元素为 null,或如果调用处理程序 h 为 null
从中可以看出它有三个参数,分别是classlcoder、interface、InvocationHandler.只要我们把这三个参数传递给他,它就可以 返回给我们一个代理对象,访问这个代理对象就可以实现对原对象的扩展 。接下来,我们用代码来实现它 。
3.3:代码场景
我们来做这样一个场景,我们实现一个计算器,计算器里面有加减乘除方法,然后我们实现这个计算的接口,有具体的类和被代理的类,我们通过动态代理来生成代理类,而不用自己去建了,好了,看接下来的代码:
3.4:动态代理的代码实现
3.4.1:首先我们新建一个接口,命名为Calculator ,声明四个方法:
public interface Calculator {int add(int i,int j);//加int sub(int i,int j);//减int mul(int i,int j);//乘double div(int i,int j);//除}3.4.2:新建一个实现类,命名为CalculatorImpl ,也就是被代理类
public class CalculatorImplimplements Calculator{@Overridepublic int add(int i, int j) {return i+j;}@Overridepublic int sub(int i, int j) {return i-j;}@Overridepublic int mul(int i, int j) {return i*j;}@Overridepublic double div(int i, int j) {return(i/j);}}


推荐阅读