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

 更新时间:2016年05月09日 09:42:06   作者:layznet  
这篇文章主要介绍了Java使用设计模式中的代理模式构建项目的实例展示,代理模式中的代理对象可以在客户端和目标对象之间起到中介的作用,需要的朋友可以参考下

概念

代理模式(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)高扩展性

相关文章

  • java如何用递归方法求阶乘

    java如何用递归方法求阶乘

    这篇文章主要介绍了java 用递归方法求阶乘的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • springcloud 熔断监控Hystrix Dashboard和Turbine

    springcloud 熔断监控Hystrix Dashboard和Turbine

    这篇文章主要介绍了springcloud 熔断监控Hystrix Dashboard和Turbine,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-08-08
  • Java中的DelayQueue源码解析

    Java中的DelayQueue源码解析

    这篇文章主要介绍了Java中的DelayQueue源码解析,一个实现PriorityBlockingQueue实现延迟获取的无界队列,在创建元素时,可以指定多久才能从队列中获取当前元素,只有延时期满后才能从队列中获取元素,需要的朋友可以参考下
    2023-12-12
  • springboot排除某些自动配置的操作方法

    springboot排除某些自动配置的操作方法

    Spring Boot 提供的自动配置非常强大,某些情况下,自动配置的功能可能不符合我们的需求,需要我们自定义配置,这个时候就需要排除/禁用Spring Boot 某些类的自动化配置了,本文给大家介绍springboot排除某些自动配置的方法,感兴趣的朋友一起看看吧
    2023-08-08
  • SpringBoot如何监听redis Key变化事件案例详解

    SpringBoot如何监听redis Key变化事件案例详解

    项目中需要监听redis的一些事件比如键删除,修改,过期等,下面这篇文章主要给大家介绍了关于SpringBoot如何监听redis Key变化事件的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-08-08
  • android显示意图激活另一个Activity的方法

    android显示意图激活另一个Activity的方法

    下面小编就为大家带来一篇android显示意图激活另一个Activity的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • Spring中@RefreshScope注解的处理方法详解

    Spring中@RefreshScope注解的处理方法详解

    这篇文章主要介绍了Spring中@RefreshScope注解的处理方法详解,spring启动时会调用ClassPathBeanDefinitionScanner.java类中的doScan()对包路径下的所有class进行扫描,获取bean的定义,同时对bean的@RefreshScope(@Scope的父类)进行处理,需要的朋友可以参考下
    2023-10-10
  • ZooKeeper入门教程二在单机和集群环境下的安装搭建及使用

    ZooKeeper入门教程二在单机和集群环境下的安装搭建及使用

    本文是ZooKeeper入门系列教程,涵盖ZooKeeper的安装使及单机集群环境搭建,通过实例和大量图表,结合实战,帮助学习者理解和运用,有需要的朋友可以借鉴参考下
    2022-01-01
  • Java的Shiro框架认证流程详解

    Java的Shiro框架认证流程详解

    这篇文章主要介绍了Java的Shiro框架认证流程详解,Shiro 是一个功能强大和易于使用的安全框架,为开发人员提供一个直观而全面的解决方案的认证,授权,加密,会话管理四大功能,需要的朋友可以参考下
    2024-01-01
  • Spring中的@PathVariable注解详细解析

    Spring中的@PathVariable注解详细解析

    这篇文章主要介绍了Spring中的@PathVariable注解详细解析,@PathVariable 是 Spring 框架中的一个注解,用于将 URL 中的变量绑定到方法的参数上,它通常用于处理 RESTful 风格的请求,从 URL 中提取参数值,并将其传递给方法进行处理,需要的朋友可以参考下
    2024-01-01

最新评论