>  기사  >  Java  >  디자인 패턴에서 프록시 패턴을 사용하여 프로젝트를 빌드하는 Java의 예

디자인 패턴에서 프록시 패턴을 사용하여 프로젝트를 빌드하는 Java의 예

高洛峰
高洛峰원래의
2017-02-07 13:26:091355검색

개념

프록시 모드(Proxy): 프록시 모드는 실제로 원본 개체를 대신하여 일부 작업을 수행하는 추가 프록시 클래스입니다. 예를 들어, 법정에 갈 때 변호사를 고용해야 할 때도 있습니다. 왜냐하면 변호사는 법률에 대한 전문 지식을 갖고 있고 우리를 대신하여 우리의 생각을 표현할 수 있기 때문입니다. 프록시 모드는 두 가지 범주로 나뉩니다: 1. 정적 프록시(jdk의 메서드를 사용하지 않음) 2. 동적 프록시(jdk에서 InvocationHandler 및 Proxy 사용)
정적 프록시는 프로그래머에 의해 생성되거나 도구가 프록시 클래스의 소스 코드를 생성한 다음 프록시 클래스를 컴파일합니다. 소위 정적이란 프로그램이 실행되기 전에 이미 프록시 클래스의 바이트코드 파일이 존재하고 프록시 클래스와 대리자 클래스 간의 관계가 실행 전에 결정되는 것을 의미합니다.
동적 프록시 클래스의 소스 코드는 프로그램 실행 중 리플렉션과 같은 메커니즘을 기반으로 JVM에 의해 동적으로 생성되므로 프록시 클래스에 대한 바이트코드 파일이 없습니다. 프록시 클래스와 대리자 클래스 간의 관계는 프로그램이 실행될 때 결정됩니다.


다음은 정적 프록시의 예입니다.
클래스 다이어그램:

디자인 패턴에서 프록시 패턴을 사용하여 프로젝트를 빌드하는 Java의 예

/** 
 * 游戏者接口 
 * 
 */
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의 더 많은 예를 보려면 PHP 중국어 웹사이트에서 관련 기사를 주목하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.