上次给大家举了个例子 QQ 车的例子 QQ车装饰者模式加强QQ车的功能的方法 在不破坏原有对象的的基础上进行加强,
那么我们现在又想给QQ车 加强一些功能呢? 按照装饰者模式的思想 我们又得去写一个qqWrepper类增加功能,如果有
几十个上百个功能需要加强呢?我们就要写好几十个类 代码量太多。
有没有一种方式 能让我们获取到一个被加强的对象 而且又不需要写qqwrepper类 。 有 ,就是今天要引入的动态代理。
不用写qqwrepper,直接返回一个被加强的对象。
jdk动态代理 必须要有接口
看看jdk代理如何在不需要写装饰类的前提下 直接返回一个被加强的对象。
在java的反射包下有一个proxy类
查阅api文档
object obj= proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
JDK 中提供了这个方法 帮你创建一个实例对象,要求你传入三个参数,不需要写类 直接返回一个加强对象
第一个传入对象参数 ClassLoader:类加载器 因为它要帮你直接返回一个已被增强的对象,必须有一个对应的类加载在内存中的,
这里本应该传入的是一个 加强过对象的类加载器,但是一般传入的被加强对象的类加载器。
interfaces 传入的是增强对象的接口列表 保证被加强对象和加强对象的声明保持保持一致。
InvocationHandler 执行处理类 接口 传参数的时候一定是一个对象。InvaocationHandler接口的实现类对象
InvocationHandler接口中只有一个方法 invoke 方法
invoke(Object proxy, Method method, Object[] args) |
proxy:指的是即将被返回的已经被加强过的对象。
Method:指的是执行的方法。
args: 方法执行的参数列表
上代码看看:
public class Demo {
public static void main(String[] args) throws Exception {
final QQ qq = new QQ();
//使用动态代理 增强它
Car zengqian = (Car) Proxy.newProxyInstance(qq.getClass().getClassLoader(),qq.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
proxy 代表即将返回的代理对象
String name = method.getName();
if("run".equals(name)){
加强你想增加的方法 其他方法不需要增强 就执行原来的方法
long start = System.currentTimeMillis(); qq 车加速之前的时间
Object invoke = method.invoke(qq); 原有对象的引用
long end = System.currentTimeMillis(); qq车加速之后的时间
System.out.println(end-start);
return invoke;
}else{
method.invoke(qq,args); 调用deriver 方法需要参数 传入参数。
return 100;
}
}
});
//zengqian.run();
//zengqian.stop();
//zengqian.driver("小明");
int oilTank = zengqian.oilTank();
System.out.println(oilTank);
}
}