LOL相信大家都玩过吧,我大学同学现在已经是最强王者了,在学校段位重置时都会叫他帮我们代打定位赛,前期定位段位越高爬坑越简单,如今大学毕业,大家都各奔东西,但这段经历还是记忆犹新,下面通过代码来演示这个代打定位赛的过程吧。
英雄联盟游戏:
public interface LOLPlayer
{
//登录LOL
public void login(String user,String password);
//打定位赛
public void play();
}
英雄联盟玩家(我的账号):
public class MyPlayer implements LOLPlayer
{
private String name="";
public MyPlayer(String name)
{
this.name = name;
}
@Override
public void login(String user,String password)
{
// TODO Auto-generated method stub
System.out.println(this.name+"登录LOL成功");
}
@Override
public void play()
{
// TODO Auto-generated method stub
System.out.println(this.name+"打定位赛");
}
}
代练玩家(我同学):
public class ProxyPlayer implements LOLPlayer
{
LOLPlayer lolPlayer =null ;
public ProxyPlayer(LOLPlayer lolPlayer)
{
this.lolPlayer = lolPlayer;
}
//代练登录
@Override
public void login(String user,String password)
{
// TODO Auto-generated method stub
this.lolPlayer.login(user,password);
}
//代打定位赛
@Override
public void play()
{
// TODO Auto-generated method stub
this.lolPlayer.play();
}
}
场景类:
public class Client
{
public static void main(String[] args)
{
//我的账号
LOLPlayer player = new MyPlayer("xiaoxsen");
//代练者
LOLPlayer proxy = new ProxyPlayer(player);
System.out.println("======代打开始====");
//代练登录
proxy.login("xiaoxsen","123");
//代打定位赛
proxy.play();
System.out.println("======代打结束====");
}
}
代打定位赛过程执行结果:
======代打开始====
xiaoxsen登录LOL成功
xiaoxsen打定位赛
======代打结束====
定位赛打完了,但是自己没有打一把,段位就有了,这就是代理模式
代理模式定义
代理模式是一种使用率非常高的模式,其定义如下:
Provide a surrogate or placeholder for another object to contrl access to it.(为其他对象提供一种代理以控制这个对象的访问。)
代理模式有以下3个角色:
Subject抽象主题角色:抽象主题角色可以是抽象类也可以是接口,是一个最普通的业务类型定义,比如上述的LOLPlayer类。
RealSubject具体主题角色:也叫做被委托角色,被代理角色,他是业务的具体执行者,比如上述的MyPlayer类。
Proxy代理主题角色:也叫做委托类,代理类。他负责对真实角色的应用,把所有抽象主题类定义的方法限制委托给真实的主题角色实现,比如上述的ProxyPlayer类。
代理模式的优点:
职责清晰
高扩展性
智能化
代理模式的扩展:
普通代理:要求客户端只出现代理类,不能访问真实角色,我们需要做如下的修改:
英雄联盟游戏玩家(我的账号):
public class MyPlayer implements LOLPlayer
{
private String name="";
public MyPlayer(LOLPlayer player,String name)
{
if(player==null)
{
System.out.println("不能创建真实角色");
}else {
this.name = name;
}
}
@Override
public void login(String user,String password)
{
// TODO Auto-generated method stub
System.out.println(this.name+"登录LOL成功");
}
@Override
public void play()
{
// TODO Auto-generated method stub
System.out.println(this.name+"打定位赛");
}
}
代练玩家(我同学):
public class ProxyPlayer implements LOLPlayer
{
LOLPlayer lolPlayer =null ;
public ProxyPlayer(String name)
{
lolPlayer = new MyPlayer(this,name);
}
//代练登录
@Override
public void login(String user,String password)
{
// TODO Auto-generated method stub
this.lolPlayer.login(user,password);
}
//代打定位赛
@Override
public void play()
{
// TODO Auto-generated method stub
this.lolPlayer.play();
}
}
代打场景:
public class Client
{
public static void main(String[] args)
{
//代练者
LOLPlayer proxy = new ProxyPlayer("xiaoxsen");
System.out.println("======代打开始====");
//代练登录
proxy.login("xiaoxsen","123");
//代打定位赛
proxy.play();
System.out.println("======代打结束====");
}
}
代打定位赛结果:
======代打开始====
xiaoxsen登录LOL成功
xiaoxsen打定位赛
======代打结束====
效果是一样的,只是隐藏了真实角色,屏蔽了真实角色变更对高层的影响。
动态代理:面向切面编程(AOP)其核心就是动态代理机制,下面我们用动态代理来实现这个代打过程。
动态代理类:
public class DynamicProxy implements InvocationHandler
{
//被代理者的实例
Object object =null;
public DynamicProxy(Object obj)
{
object = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable
{
// TODO Auto-generated method stub
Object ob = method.invoke(object, args);
return ob;
}
}
动态代理场景类:
public class Client1
{
public static void main(String[] args)
{
LOLPlayer player = new MyPlayer("xiaoxsen");
InvocationHandler handle = new DynamicProxy(player);
//获得类加载器
ClassLoader cl = player.getClass().getClassLoader();
//代练者
LOLPlayer proxy = (LOLPlayer) Proxy.newProxyInstance(cl, new Class[]{LOLPlayer.class}, handle);
System.out.println("======代打开始====");
//代练登录
proxy.login("xiaoxsen","123");
//代打定位赛
proxy.play();
System.out.println("======代打结束====");
}
}
执行结果:
======代打开始====
xiaoxsen登录LOL成功
xiaoxsen打定位赛
======代打结束====
发现结果是一样的,我们并没有创建代理类,我们在代码中动态生成代理类,完成代打过程,这就是动态代理模式,当然我们可以在invoke方法前后做一些操作达到一定的控制作用,这也是面向切面编程的关键。