设计模式之代理模式

来源:互联网 发布:淘宝模板什么意思 编辑:程序博客网 时间:2024/06/05 20:14

如有转载,请申明:

转载至 http://blog.csdn.net/qq_35064774/article/details/51971796



1 什么是代理模式

代理模式是对象的结构模式。代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。

 

 

 

2 怎么实现代理模式

 

首先我们要知道代理模式按使用目的可分为以下几种:

 * 远程代理:为一个位于不同的地址空间的对象提供一个局域代表对象。

 * 虚拟代理:根据需要创建一个资源消耗较大的对象,使得此对象只在需要时才会被真正创建。

 * 保护代理:控制对一个对象的访问,如果需要,可以给不同的用户提供不同级别的使用权限。

智能引用代理:当一个对象被引用时,提供一些额外的操作,比如将此对象调用的次数记录下来等。

 

 

代理的实现比较复杂,幸运的是,Java支持代理模式。

Java sdk中提供了代理类ProxyInvocationHandler接口。

 

我们尝试着解决下面提出的问题。

 * 现有一个Car对象,其中有movefix方法,我们需要计算两个方法的执行时间。但又不能修改Car的方法。

 

首先,我们按照要求,写一个Car类,有movefix两个方法,但为了更方便的实现代理和增强扩展性,我们把这movefix抽象成两个接口MoveableFixable。然后由Car实现这两个接口。


package com.ittianyu.proxy.dynamic;public interface Moveable {void move();}

 

package com.ittianyu.proxy.dynamic;public interface Fixable {void fix(String thing);}

 

package com.ittianyu.proxy.dynamic;public class Car implements Moveable, Fixable{@Overridepublic void move() {System.out.println("moving...");try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}@Overridepublic void fix(String thing) {System.out.println("fixing...");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}


 

再有了Car类之后,我们就需要定义一个实现了InvocationHandler接口的类。

这个类就是Car的代理类会调用的一个接口实现类。

而代理应该做的是,计算被代理类的方法执行前后所用的时间。

我们先考虑一下如何计算某一段代码执行的时间。

大部分童鞋应该都想到了,时间差。

也就是执行那段代码前后都调用System.currentTimeMillis();取得时间戳,然后求差就得到了结果。

所以我们在代理类里也是需要在前后各取一次启动时间。

 

package com.ittianyu.proxy.dynamic;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;public class TimeInvocationHandler implements InvocationHandler {private Object object;private long start;private long end;// object为被代理的对象,需要我构建的时候传入public TimeInvocationHandler(Object object) {super();this.object = object;}// proxy是代理类@Overridepublic Object invoke(Object proxy, Method method, Object[] args)throws Throwable {//在执行被代理类的方法前的处理this.doBefore();// 执行被代理类的方法,object是被代理的对象,method是它的方法,args是它的所有参数,returnObject是方法返回值Object returnObject = method.invoke(object, args);//在执行被代理类的方法后的处理this.doAfter();return returnObject;}private void doBefore() {start = System.currentTimeMillis();}private void doAfter() {end = System.currentTimeMillis();System.out.println("运行耗时(ms)" + (end - start));}}


 

最后我们开始测试,定义一个Test类,在main方法中测试

 

package com.ittianyu.proxy.dynamic;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Proxy;public class Test {public static void main(String[] args) {Car car = new Car();InvocationHandler handler = new TimeInvocationHandler(car);Object proxy = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), car.getClass().getInterfaces(), handler);((Moveable)proxy).move();((Fixable)proxy).fix("轮胎");}}


这里的Proxy.newProxyInstance返回的类,就是我们的代理类,这个类实现了两个接口,所以我们可以分别转成两个接口来调用其中的方法。

 

 

3 在什么情况下使用代理模式

 

 * 当我们需要对某一对象加以不同的控制,但又不能破坏对象内部结构时,就需要代理模式。比如,我们需要在执行某方法之前和之后检测权限或者进行一些处理。

 

4 代理模式的优点和缺点

根据代理种类不同,其特点也不同。

 

优点:

 * 远程代理:系统可以将网络的细节隐藏起来,使得客户端不必考虑网络的存在。

 * 虚拟代理:代理对象可以在必要的时候才被代理的对象加载。

 * 保护代理:它可以在运行时间对用户的有关权限进行检查,然后在核实后决定将调用传递给被代理的对象。

 * 智能引用代理:在访问一个对象时可以执行一些内务处理操作,比如计数操作等。

 

缺点:

 * 远程代理:客户不会意识到会启动一个i额耗时的远程调用,因此,客户没有必要的思想准备。

 

1 0
原创粉丝点击