场景:网瘾少年玩游戏,打怪升级
所有玩家接口,定义玩家的行为(Subject)
public interface IGamePlayer {
// 登录
void login(String name, String password);
// 打怪
void killBoss();
// 升级
void upgrade();
}
模拟玩家游戏场景(RealSubject)
public class GamePlayer implements IGamePlayer{
private String mName;
public GamePlayer(String name) {
this.mName = name;
}
@Override
public void login(String name, String password) {
System.out.println("用户"+name+"登录成功");
}
@Override
public void killBoss() {
System.out.println("用户"+mName+"开启超神模式,十连杀");
}
@Override
public void upgrade() {
System.out.println("恭喜用户"+mName+"成功升到110级");
}
}
客户端
GamePlayer gamePlayer = new GamePlayer("jordan");
gamePlayer.login("jordan","jjj");
gamePlayer.killBoss();
gamePlayer.upgrade();
● 客户端运行结果
用户jordan登录成功
用户jordan开启超神模式,十连杀
恭喜用户jordan成功升到110级
游戏代理者,同样需要登录游戏,打怪,升级(Proxy)
public class GamePlayProxy implements IGamePlayer{
private IGamePlayer mIGamePlayer;
public GamePlayProxy(IGamePlayer iGamePlayer ) {
this.mIGamePlayer = iGamePlayer;
}
// 代练升级
@Override
public void login(String name, String password) {
mIGamePlayer.login(name,password);
}
// 代练打怪
@Override
public void killBoss() {
mIGamePlayer.killBoss();
}
// 代练升级
@Override
public void upgrade() {
mIGamePlayer.upgrade();
}
}
客户端
GamePlayer gamePlayer = new GamePlayer("jordan");
// 游戏代练者,需要以游戏玩家的身份玩游戏
GamePlayProxy gamePlayProxy =new GamePlayProxy(gamePlayer);
gamePlayProxy.login("jordan","jjj");
gamePlayProxy.killBoss();
gamePlayProxy.upgrade();
现在有个非常流行的程序叫做面向切面编程(AOP),其核心就是采用了动态代理的方式。怎么用?Java为我们提供了一个便捷的动态代理接口 InvocationHandler,实现该接口需要重写其调用方法invoke
public class DynamicProxy implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return null;
}
}
在这里,我们主要通过invoke()来调用具体的被代理方法,也就是真实的方法。 接下来我们看一下动态代理的实际用法,接着上面游戏代练的例子。新增一个GamePlayIH类并实现InvocationHandler接口,然后动态代理是根据被代理的接口生成所有的方法
动态代理类
public class GamePlayIH implements InvocationHandler {
private Object mObject;
public GamePlayIH(Object object) {
this.mObject = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(this.mObject, args);
return result;
}
}
客户端
IGamePlayer gamePlayer = new GamePlayer("jordan");
InvocationHandler handler = new GamePlayIH(gamePlayer);
ClassLoader classLoader = gamePlayer.getClass().getClassLoader();
// 动态的产生一个代理者
IGamePlayer proxy = (IGamePlayer) Proxy.newProxyInstance(classLoader, new Class[]{IGamePlayer.class}, handler);
// 代替玩家开始犀利的操作
proxy.login("jordan","jjj");
proxy.killBoss();
proxy.upgrade();
程序完美运行,Log显示跟上面一样,接下来让我们看看程序是怎么实现的,我们知其然还要知所以然。
ClassLoader classLoader = gamePlayer.getClass().getClassLoader();
// 动态的产生一个代理者
IGamePlayer proxy = (IGamePlayer) Proxy.newProxyInstance(classLoader, new Class[]{IGamePlayer.class}, handler);
我们看一下这个方法,该方法时重新生成了一个对象,为什么要重新生成?因为我们需要用代理,new Class[]{IGamePlayer.class}是说查找到该类的所有接口,然后实现接口 的所有方法。当然了,方法都是空的,由谁负责接管呢?handler这个对象,于是我们知道了一个类的动态代理是这样一个类由InvocationHandler的实现类实现所有的方法, 由其invoke()接管所有方法的实现。
图片摘自网络!