类图

Java 实现代理(Proxy)模式_System


​​


1. /**
2. * 游戏者接口
3. *
4. */
5. public interface IGamePlayer {
6.
7. // 登录游戏
8. public void login(String user, String password);
9.
10. // 杀怪,网络游戏的主要特色
11. public void killBoss();
12.
13. // 升级
14. public void upgrade();
15.
16. }

​​


1. /**
2. * 游戏者
3. *
4. */
5. public class GamePlayer implements IGamePlayer {
6.
7. private String name = "";
8.
9. // 通过构造函数传递名称
10. public GamePlayer(String _name) {
11. this.name = _name;
12. }
13.
14. // 打怪,最期望的就是杀老怪
15.
16. public void killBoss() {
17.
18. this.name + " 在打怪!");
19.
20. }
21.
22. // 进游戏之前你肯定要登录吧,这是一个必要条件
23. public void login(String user, String password) {
24. "登录名为" + user + " 的角色 " + this.name + "登录成功!");
25. }
26.
27. // 升级,升级有很多方法,花钱买是一种,做任务也是一种
28. public void upgrade() {
29. this.name + " 又升了一级!");
30. }
31.
32. }

​​


1. /**
2. * 客户端 对被代理对象不可见
3. */
4. public class GamePlayerProxy implements IGamePlayer {
5.
6. private IGamePlayer gamePlayer = null;//被代理对象
7.
8. // 通过构造函数传递要对谁进行代练
9. public GamePlayerProxy(String username) {
10. this.gamePlayer = new GamePlayer(username);
11. }
12.
13. // 代练杀怪
14. public void killBoss() {
15. this.gamePlayer.killBoss();
16. }
17.
18. // 代练登录
19. public void login(String user, String password) {
20. this.gamePlayer.login(user, password);
21. }
22.
23. // 代练升级
24. public void upgrade() {
25. this.gamePlayer.upgrade();
26. }
27.
28. }

​​


1. /*
2. * 客户端 对被代理对象不可见
3. */
4. public class GamePlayerProxy2 implements IGamePlayer {
5.
6. private IGamePlayer gamePlayer = null;//被代理对象
7.
8. // 通过构造函数传递要对谁进行代练
9. public GamePlayerProxy2(String username) {
10. this.gamePlayer = new GamePlayer(username);
11. }
12.
13. // 代练杀怪
14. public void killBoss() {
15. this.gamePlayer.killBoss();
16. }
17.
18. // 代练登录
19. public void login(String user, String password) {
20. "登录时间是:" + new Date().toLocaleString());
21. this.gamePlayer.login(user, password);
22. }
23.
24. // 代练升级
25. public void upgrade() {
26. this.gamePlayer.upgrade();
27. "升级时间是:" + new Date().toLocaleString());
28. }
29.
30. }



​​



    1. /*
    2. * 客户端 对被代理对象不可见
    3. */
    4. public class GamePlayerProxy3 {
    5.
    6. private IGamePlayer gamePlayer;
    7. // 通过构造函数传递 被代练(代理)对象
    8. public GamePlayerProxy3(IGamePlayer gamePlayer) {
    9. this.gamePlayer = gamePlayer;
    10. "我是一名代练,我玩的角色是别人的,可以动态传递进来");
    11. }
    12.
    13. public IGamePlayer getProxy() {
    14. return (IGamePlayer) Proxy.newProxyInstance(this.getClass().getClassLoader(),
    15. new Class[]{IGamePlayer.class}, new MyInvocationHandler());
    16. }
    17.
    18. private class MyInvocationHandler implements InvocationHandler {
    19.
    20. @Override
    21. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    22. if (method.getName().equals("login")) {
    23. "登录时间是:" + new Date().toLocaleString());
    24. if (method.getName().equals("upgrade")) {
    25. "升级时间是:" + new Date().toLocaleString());
    26. }
    27. method.invoke(gamePlayer, args);
    28. return null;
    29. }
    30.
    31. }
    32. }




    ​​

    1. /*
    2. * 代理模式:为其他对象提供一种代理以控制对这个对象的访问。
    3. * 在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用
    4. * 优点
    5. (1).职责清晰
    6. 真实的角色就是实现实际的业务逻辑,不用关心其他非本职责的事务,通过后期的代理完成一件完成事务,附带的结果就是编程简洁清晰。
    7. (2).代理对象可以在客户端和目标对象之间起到中介的作用,这样起到了的作用和保护了目标对象的作用。
    8. (3).高扩展性
    9. 模式结构
    10. 一个是真正的你要访问的对象(目标类),一个是代理对象,真正对象与代理
    11. 对象实现同一个接口,先访问代理类再访问真正要访问的对象。
    12.
    13. 在装饰器模式和代理模式之间还是有很多差别的。装饰器模式关注于在一个对象上动态的添加方法,然而代理模式关注于控制对对象的访问。
    14. 换句话 说,用代理模式,代理类(proxy class)可以对它的客户隐藏一个对象的具体信息。因此,当使用代理模式的时候,我们常常在一个代理类中创建一个对象的实例。
    15. 并且,当我们使用装饰器模 式的时候,我们通常的做法是将原始对象作为一个参数传给装饰者的构造器。
    16. 我们可以用另外一句话来总结这些差别:使用代理模式,代理和真实对象之间的的关系通常在编译时就已经确定了,而装饰者能够在运行时递归地被构造。
    17. */
    18. public class Test {
    19. public static void main(String[] args) {
    20. /*
    21. * 普通的静态代理: 客户端不知道被代理对象,由代理对象完成其功能的调用
    22. */
    23. new GamePlayerProxy("X");
    24. "开始时间是:" + new Date().toLocaleString());
    25. "zhangSan", "abcd");
    26. proxy.killBoss();
    27. proxy.upgrade();
    28. "结束时间是:" + new Date().toLocaleString());
    29.
    30. System.out.println();
    31.
    32. /*
    33. * 代理对象 增强了 被代理对象的功能
    34. */
    35. new GamePlayerProxy2("M");
    36. "lisi", "efg");
    37. proxy2.killBoss();
    38. proxy2.upgrade();
    39.
    40. System.out.println();
    41.
    42. /*
    43. * 动态代理:使用jdk提供的InvocationHandler,反射调用被代理对象的方法
    44. * 结合java.reflect.Proxy 产生代理对象
    45. * 动态传入被代理对象构造InvocationHandler,在handler中的invoke时可以增强被代理对象的方法的功能
    46. * 或者说:(面向切面:)在什么地方(连接点), 执行什么行为(通知)
    47. * GamePlayerProxy3中是方法名为login时通知开始时间,upgrade时通知结束时间
    48. */
    49. new GamePlayerProxy3(new GamePlayer("Y"));
    50. IGamePlayer dynamicPlayer = dynamic.getProxy();
    51. "wangwu", "1234");
    52. dynamicPlayer.killBoss();
    53. dynamicPlayer.upgrade();
    54. /*
    55. * 面向切面: 一些相似的业务逻辑需要加在众多的地方,那们就可以把它提取到切面中, 切面也就是事务切面:如日志切面、权限切面、业务切面
    56. */
    57. }
    58. }


    打印:


    ​​


    1. 开始时间是:2014-10-8 17:19:05  
    2. 登录名为zhangSan 的角色 X登录成功!
    3. X 在打怪!
    4. X 又升了一级!
    5. 结束时间是:2014-10-8 17:19:05
    6.
    7. 登录时间是:2014-10-8 17:19:05
    8. 登录名为lisi 的角色 M登录成功!
    9. M 在打怪!
    10. M 又升了一级!
    11. 升级时间是:2014-10-8 17:19:05
    12.
    13. 我是一名代练,我玩的角色是别人的,可以动态传递进来
    14. 登录时间是:2014-10-8 17:19:05
    15. 登录名为wangwu 的角色 Y登录成功!
    16. Y 在打怪!
    17. 升级时间是:2014-10-8 17:19:05
    18. Y 又升了一级!