首页 > 编程 > Java > 正文

Java使用设计模式中的代理模式构建项目的实例展示

2019-11-26 14:22:12
字体:
来源:转载
供稿:网友

概念

代理模式(Proxy):代理模式其实就是多一个代理类出来,替原对象进行一些操作。比如咱有的时候打官司需要请律师,因为律师在法律方面有专长,可以替咱进行操作表达咱的想法,这就是代理的意思。代理模式分为两类:1、静态代理(不使用jdk里面的方法);2、动态代理(使用jdk里面的InvocationHandler和Proxy)。
静态代理由程序员创建或工具生成代理类的源码,再编译代理类。所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和委托类的关系在运行前就确定了。
动态代理类的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以不存在代理类的字节码文件。代理类和委托类的关系是在程序运行时确定。

示例
这里我们举一个静态代理的例子:
类图:

20165993519867.jpg (341×215)

/**  * 游戏者接口  *  */ 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)高扩展性

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表