Java使用设计模式中的代理模式构建项目的实例展示
程序员文章站
2024-03-11 22:06:55
概念
代理模式(proxy):代理模式其实就是多一个代理类出来,替原对象进行一些操作。比如咱有的时候打官司需要请律师,因为律师在法律方面有专长,可以替咱进行操作表达咱的想...
概念
代理模式(proxy):代理模式其实就是多一个代理类出来,替原对象进行一些操作。比如咱有的时候打官司需要请律师,因为律师在法律方面有专长,可以替咱进行操作表达咱的想法,这就是代理的意思。代理模式分为两类:1、静态代理(不使用jdk里面的方法);2、动态代理(使用jdk里面的invocationhandler和proxy)。
静态代理由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。
动态代理类的源码是在程序运行期间由jvm根据反射等机制动态的生成,所以不存在代理类的字节码文件。代理类和委托类的关系是在程序运行时确定。
示例
这里我们举一个静态代理的例子:
类图:
/** * 游戏者接口 * */ public interface igameplayer { // 登录游戏 public void login(string user, string password); // 杀怪,网络游戏的主要特色 public void killboss(); // 升级 public void upgrade(); }
/** * 游戏者 * */ public class gameplayer implements igameplayer { private string name = ""; // 通过构造函数传递名称 public gameplayer(string _name) { this.name = _name; } // 打怪,最期望的就是杀老怪 public void killboss() { system.out.println(this.name + " 在打怪!"); } // 进游戏之前你肯定要登录吧,这是一个必要条件 public void login(string user, string password) { system.out.println("登录名为" + user + " 的角色 " + this.name + "登录成功!"); } // 升级,升级有很多方法,花钱买是一种,做任务也是一种 public void upgrade() { system.out.println(this.name + " 又升了一级!"); } }
/** * 客户端 对被代理对象不可见 */ public class gameplayerproxy implements igameplayer { private igameplayer gameplayer = null;//被代理对象 // 通过构造函数传递要对谁进行代练 public gameplayerproxy(string username) { this.gameplayer = new gameplayer(username); } // 代练杀怪 public void killboss() { this.gameplayer.killboss(); } // 代练登录 public void login(string user, string password) { this.gameplayer.login(user, password); } // 代练升级 public void upgrade() { this.gameplayer.upgrade(); } }
/* * 客户端 对被代理对象不可见 */ public class gameplayerproxy2 implements igameplayer { private igameplayer gameplayer = null;//被代理对象 // 通过构造函数传递要对谁进行代练 public gameplayerproxy2(string username) { this.gameplayer = new gameplayer(username); } // 代练杀怪 public void killboss() { this.gameplayer.killboss(); } // 代练登录 public void login(string user, string password) { system.out.println("登录时间是:" + new date().tolocalestring()); this.gameplayer.login(user, password); } // 代练升级 public void upgrade() { this.gameplayer.upgrade(); system.out.println("升级时间是:" + new date().tolocalestring()); } }
/* * 客户端 对被代理对象不可见 */ public class gameplayerproxy3 { private igameplayer gameplayer; // 通过构造函数传递 被代练(代理)对象 public gameplayerproxy3(igameplayer gameplayer) { this.gameplayer = gameplayer; system.out.println("我是一名代练,我玩的角色是别人的,可以动态传递进来"); } public igameplayer getproxy() { return (igameplayer) proxy.newproxyinstance(this.getclass().getclassloader(), new class[]{igameplayer.class}, new myinvocationhandler()); } private class myinvocationhandler implements invocationhandler { @override public object invoke(object proxy, method method, object[] args) throws throwable { if (method.getname().equals("login")) { system.out.println("登录时间是:" + new date().tolocalestring()); } if (method.getname().equals("upgrade")) { system.out.println("升级时间是:" + new date().tolocalestring()); } method.invoke(gameplayer, args); return null; } } }
public class test { public static void main(string[] args) { /* * 普通的静态代理: 客户端不知道被代理对象,由代理对象完成其功能的调用 */ igameplayer proxy = new gameplayerproxy("x"); system.out.println("开始时间是:" + new date().tolocalestring()); proxy.login("zhangsan", "abcd"); proxy.killboss(); proxy.upgrade(); system.out.println("结束时间是:" + new date().tolocalestring()); system.out.println(); /* * 代理对象 增强了 被代理对象的功能 */ igameplayer proxy2 = new gameplayerproxy2("m"); proxy2.login("lisi", "efg"); proxy2.killboss(); proxy2.upgrade(); system.out.println(); /* * 动态代理:使用jdk提供的invocationhandler,反射调用被代理对象的方法 * 结合java.reflect.proxy 产生代理对象 * 动态传入被代理对象构造invocationhandler,在handler中的invoke时可以增强被代理对象的方法的功能 * 或者说:(面向切面:)在什么地方(连接点), 执行什么行为(通知) * gameplayerproxy3中是方法名为login时通知开始时间,upgrade时通知结束时间 */ gameplayerproxy3 dynamic = new gameplayerproxy3(new gameplayer("y")); igameplayer dynamicplayer = dynamic.getproxy(); dynamicplayer.login("wangwu", "1234"); dynamicplayer.killboss(); dynamicplayer.upgrade(); /* * 面向切面: 一些相似的业务逻辑需要加在众多的地方,那们就可以把它提取到切面中, 切面也就是事务切面:如日志切面、权限切面、业务切面 */ } }
打印:
开始时间是:2014-10-8 17:19:05 登录名为zhangsan 的角色 x登录成功! x 在打怪! x 又升了一级! 结束时间是:2014-10-8 17:19:05 登录时间是:2014-10-8 17:19:05 登录名为lisi 的角色 m登录成功! m 在打怪! m 又升了一级! 升级时间是:2014-10-8 17:19:05 我是一名代练,我玩的角色是别人的,可以动态传递进来 登录时间是:2014-10-8 17:19:05 登录名为wangwu 的角色 y登录成功! y 在打怪! 升级时间是:2014-10-8 17:19:05 y 又升了一级!
优点
(1)职责清晰
真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件完成事务,附带的结果就是编程简洁清晰。
(2)代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了的作用和保护了目标对象的作用。
(3)高扩展性