代理模式之动态代理
上一篇文章https://blog.csdn.net/qq_28044241/article/details/82534196已经介绍了静态代理的基本原理和实现:所谓代理,其实就是找一个对象(如上一篇文章中的游戏代练)代替自己去干一些事(如上篇文章中的登陆、打怪、升级等),其反应到代码中就是去实现一个代理类,并调用自己(被代理对象)的方法。在代理类执行被代理对象的方法之前或之后,代理类可以加入自己的一些处理逻辑(比如代练在登陆被代理对象的账号之前需要记录一下日志,在升级之后需要记录一下日志以便好找被代理对象讨要代理费等)。
在上一篇文章中,有多少种游戏我就需要准备多少个代理类(方便为不同的游戏玩家代练),但是呢,在进行代练的过程中,每个游戏我们都需要在登陆时记录日志,升级后记录日志,这样下来代理类就会膨胀,代码就会越来越乱。有没有一种解决方案能够做到针对某一类需求(记录日志),我们只生成一个代理类,但是还能完成这一类需求。比如,就是为所有游戏类记录日志,不管你是王者荣耀还是斗地主(实现统一接口)???
反观我们实现静态代理的过程,我们为每一个游戏手动实现了一个代理类,从而实现了代理。那么,我们可不可以动态去生成一个类似的代理类,然后你把你需要代理的对象以及需要调用的方法告诉这个代理类,然后这个代理类就能帮你完成你需要的操作呢?答案是可以的,这就是动态代理产生的缘由。
关于动态代理的更多原理及详细信息可以参看https://blog.csdn.net/Goskalrie/article/details/52458773,或者下载:链接:https://pan.baidu.com/s/1Xcr9mDsiPW2EqjH75VViwQ 密码:py29 本文在这给出简单的代码实现。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DynamicProxy {
public static void main(String[] args) {
XXXGamePlayer player = new XXXGamePlayer("李四");
InvocationHandler tHandler = new TimeHandler(player);
GamePlayer proxy = (GamePlayer)
//Proxy.newProxyInstance()生成一个代理对象,并在tHandler中调用需要执行的方法
Proxy.newProxyInstance(DynamicProxy.class.getClassLoader(),
new Class[] { GamePlayer.class }, tHandler);
InvocationHandler h = new Loghandler(proxy);
GamePlayer newProxy = (GamePlayer) Proxy.newProxyInstance(DynamicProxy.class.getClassLoader(),
new Class[] { GamePlayer.class }, h);
newProxy.login();
}
}
class TimeHandler implements InvocationHandler{
private GamePlayer target;
public TimeHandler(GamePlayer target) {
super();
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(System.currentTimeMillis());
method.invoke(target, args);
System.out.println(System.currentTimeMillis());
return null;
}
}
class Loghandler implements InvocationHandler {
private GamePlayer target;
public Loghandler(GamePlayer target) {
super();
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName() + " method start......");
method.invoke(target, args);
System.out.println(method.getName() + " method finished......");
return null;
}
}