代理模式

xiaoxiao2025-08-09  8

我们把这段打游戏的过程系统化,非常简单的一个过程,如图

package DaiLiP; public interface IGamePlayer { public void login(String user,String password); public void killboss(); public void upgrade(); } package DaiLiP; public class GamePlayer implements IGamePlayer{ private String name = ""; public GamePlayer(String _name){ this.name = _name; } @Override public void login(String user, String password) { System.out.println(user+"login up"); } @Override public void killboss() { System.out.println(this.name+"kill boss"); } @Override public void upgrade() { System.out.println(this.name+"up grade"); } } package DaiLiP; public class Client { public static void main(String[] args){ GamePlayer zz = new GamePlayer("zs"); zz.login("zs","password"); zz.killboss(); zz.upgrade(); } }

找个代练;

package DaiLiP; public class ProxyGamePlayer implements IGamePlayer{ private IGamePlayer gamePlayer = null; public ProxyGamePlayer(IGamePlayer iGamePlayer){ this.gamePlayer = iGamePlayer; } @Override public void login(String user, String password) { this.gamePlayer.login(user,password); } @Override public void killboss() { this.gamePlayer.killboss(); } @Override public void upgrade() { this.gamePlayer.upgrade(); } } package DaiLiP; public class Client { public static void main(String[] args){ IGamePlayer zz = new GamePlayer("zs"); IGamePlayer dl = new ProxyGamePlayer(zz); dl.login("user","password"); dl.killboss(); dl.upgrade(); // zz.login("zs","password"); // zz.killboss(); // zz.upgrade(); } }

代理模式的通用类图:

代理模式也叫做委托模式,它是一项基本设计技巧。许多其他的模式,如状态模式、策 略模式、访问者模式本质上是在更特殊的场合采用了委托模式,而且在日常的应用中,代理 模式可以提供非常好的访问控制。在一些著名开源软件中也经常见到它的身影,如Struts2的 Form元素映射就采用了代理模式(准确地说是动态代理模式)。我们先看一下类图中的三个 角色的定义: ● Subject抽象主题角色 抽象主题类可以是抽象类也可以是接口,是一个最普通的业务类型定义,无特殊要求。 ● RealSubject具体主题角色

 

代理模式的优点 ● 职责清晰 真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理 完成一件事务,附带的结果就是编程简洁清晰。 ● 高扩展性 具体主题角色是随时都会发生变化的,只要它实现了接口,甭管它如何变化,都逃不脱 如来佛的手掌(接口),那我们的代理类完全就可以在不做任何修改的情况下使用。 ● 智能化 这在我们以上的讲解中还没有体现出来,不过在我们以下的动态代理章节中你就会看到 代理的智能化有兴趣的读者也可以看看Struts是如何把表单元素映射到对象上的。我相信第一次接触到代理模式的读者肯定很郁闷,为什么要用代理呀?想想现实世界 吧,打官司为什么要找个律师?因为你不想参与中间过程的是是非非,只要完成自己的答辩 就成,其他的比如事前调查、事后追查都由律师来搞定,这就是为了减轻你的负担。代理模 式的使用场景非常多,大家可以看看Spring AOP,这是一个非常典型的动态代理。

 

动态代理才是重头戏。什么是动态代理?动态代理是在实现阶段不用关心代理谁,而在运行阶段 才指定代理哪一个对象。相对来说,自己写代理类的方式就是静态代理。 也叫做被委托角色、被代理角色。它才是冤大头,是业务逻辑的具体执行者。 ● Proxy代理主题角色 也叫做委托类、代理类。它负责对真实角色的应用,把所有抽象主题类定义的方法限制 委托给真实主题角色实现,并且在真实主题角色处理完毕前后做预处理和善后处理工作。

AOP(Aspect Oriented Programming),其核心就是采用了动态代理机制。

以打游戏为例,类图修改一下以实现动态代理,如图

 

在类图中增加了一个InvocationHandler接口和GamePlayIH类,作用就是产生一个对象的 代理对象,其中InvocationHandler是JDK提供的动态代理接口,对被代理类的方法进行代理。 我们来看程序,接口保持不变,实现类也没有变化。

package DaiLiP; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class GamePlayIH implements InvocationHandler{ //被代理者 Class cls = null; //被代理的实例 Object obj = null; //我要代理谁 public GamePlayIH(Object _obj){ this.obj = _obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = method.invoke(this.obj,args); return result; } } package DaiLiP; import javax.xml.crypto.Data; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Proxy; public class ClientD { public static void main(String[] args) { IGamePlayer player = new GamePlayer("lisi"); InvocationHandler handler = new GamePlayIH(player); System.out.println("时间"); ClassLoader cl = player.getClass().getClassLoader(); IGamePlayer proxy = (IGamePlayer) Proxy.newProxyInstance(cl,new Class[] {IGamePlayer.class},handler); proxy.login("lisi","password"); proxy.killboss(); proxy.upgrade(); } }

我们既没有创建代理类,也没有实现IGamePlayer接口,这就是动态代理。take it easy,动态代理可不仅仅就这么多内容,还有更重要的,如果想让游戏登录后发一个信息给我们,防止账号被人盗用嘛,该怎么处理?直接修改被代理类 GamePlayer?这不是一个好办法,好办法如代码:

仅仅是在invoke加入个if;

package DaiLiP; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class GamePlayIH implements InvocationHandler{ //被代理者 Class cls = null; //被代理的实例 Object obj = null; //我要代理谁 public GamePlayIH(Object _obj){ this.obj = _obj; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result = method.invoke(this.obj,args); if (method.getName().equalsIgnoreCase("login")){ System.out.println("账号在XX登录"); } return result; } }

有人用我的账号就发送一个信息,然后看看自己的账号是不是被人盗了,非常 好的方法,这就是AOP编程。AOP编程没有使用什么新的技术,但是它对我们的设计、编码 有非常大的影响,对于日志、事务、权限等都可以在系统设计阶段不用考虑,而在设计后通 过AOP的方式切过去。既然动态代理是如此诱人,我们来看看通用动态代理模型,类图如图

两条独立发展的线路。动态代理实现代理的职责,业务逻辑Subject实现相关的逻辑功能,两者之间没有必然的相互耦合的关系。通知Advice从另一个切面切入,最终在高层模块也就是Client进行耦合,完成逻辑的封装任务。

 

转载请注明原文地址: https://www.6miu.com/read-5034577.html

最新回复(0)