代理模式:为其他对象提供一种代理,以控制对这个对象的访问,可以去掉某些功能,或者增加某些额外的服务.
例如汽车具有行驶的功能,如果想为汽车再添加日志,记录行驶时间的工作时,便可以创建代理类进行其余的操作.
1>创建一个interface包含汽车的move()方法
package com.proxy;
/**
* Created by panlu on 15-9-5.
*/
public interface Moveable {
void move();
}
2>真实的类(Car)和代理类(ProxyCar02)都需要实现这个接口
package com.proxy;
/**
* Created by panlu on 15-9-5.
*/
//使用集合的方式进行代理模式
public class ProxyCar02 implements Moveable {
private Car car01;
public ProxyCar02(Car car01) {
super();
this.car01 = car01;
}
@Override
public void move(){
long startTime = System.currentTimeMillis();
System.out.println("汽车开始行驶...");
car01.move();
long endTime = System.currentTimeMillis();
System.out.println("汽车停止行驶... "+(endTime-startTime));
}
}
3>测试类
package com.proxy;
/**
* Created by panlu on 15-9-5.
*/
public class ClientTest {
public static void main(String[] args) {
//使用集合方式
Car c = new Car();
Moveable m1 = new ProxyCar02(c);
m1.move();
}
}
从上面的例子可以看出代理模式的工作方式,首先,因为ProxyCar02和Car都实现了共同的接口,这使我们可以在不改变原来接口的情况下,只要用Car对象的地方,都可以用ProxyCar02来代替.其在客户和真实,ProxyCar02在Client和Car之间起了一个中介作用,利用这个中介平台,我们可以在把客户请求传递给Car之前,做一些必要的预处理.
Java对代理模式的支持—–动态代理
上面的代理,我们强迫代理类ProxyCar02实现了抽象接口Moveable.这导致我们的代理类无法通用于其他接口,所以不得不为每一个接口实现一个代理类.幸好,java为代理模式提供了支持.
java主要是通过Proxy类和InvocationHandler接口来给实现对代理模式的支持的.
下面用java的代理机制来实现上面的例子
package com.jdkproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* Created by panlu on 15-9-5.
*/
//事务处理器
public class TimeHandler implements InvocationHandler {
private Object target;
public TimeHandler(Object target) {
super();
this.target = target;
}
@Override
//在该方法中添加具体的业务逻辑
/*
* proxy: 指代我们所代理的那个真实对象
* method: 指代的是我们所要调用真实对象的某个方法的Method对象
* args: 指代的是调用真实对象某个方法时接受的参数
* */
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
long startTime = System.currentTimeMillis();
System.out.println("汽车开始行驶...");
method.invoke(target);
long endTime = System.currentTimeMillis();
System.out.println("汽车停止行驶... "+(endTime-startTime));
return null;
}
}
通过上面的代码可以看出,代理类TimeHandler 并没有实现我们定义的Moveable接口,
而是实现了java的InvocationHandler接口,这样就把代理汽车角色和我们的业务代码分离开来,使代理对象能通用于其他接口.
其实InvocationHandler接口就是一种拦截机制,当系统中有了代理对象以后,对原对象(真实汽车)方法的调用,都会转由InvocationHandler接口来处理,并把方法信息以参数的形式传递给invoke方法,这样,我们就可以在invoke方法中拦截原对象的调用,并通过反射机制来动态调用原对象的方法.