黑马程序员技术交流社区

标题: 第十贴 代理、概念框架图、动态代理(1) [打印本页]

作者: jinhu358    时间: 2013-5-23 17:09
标题: 第十贴 代理、概念框架图、动态代理(1)
代理:一个角色代表别的一个角色来完成某些特定的功能。
比如:厂家,代理商,客户
客户买产品并不会直接与厂家打交道,客户只与代理商打交道,而代理商就可以对产品进行一些包装,搞一些促销及活动,提供一些售后的服务。

代理模式有三个角色: 1. 抽象主题角色 2. 代理主题角色 3. 实际被代理角色
其它类通过访问代理主题角色来访问实际被代理角色。

下面我们来个一个静态代理的实现。
我以一个坦克为例。
抽象主题角色:Moveable
  1. package com.gjy.proxy;
  2. public interface Moveable {
  3.         void move();
  4. }
复制代码
代理主题角色:TanktimeProxy
  1. package com.gjy.proxy;
  2. public class TanktimeProxy implements Moveable{
  3.        private Moveable t;
  4.        public TanktimeProxy(Moveable t) {
  5.                  super();
  6.                  this.t = t;
  7.        }
  8. @Override
  9.                 public void move() {
  10.          long time1 = System.currentTimeMillis();
  11.          System.out.println("time1="+time1);
  12.          t.move();
  13.          long time2 = System.currentTimeMillis();
  14.         System.out.println("time2="+time2);
  15.         System.out.println("运行时间为:"+(time2-time1));
  16.                 }
  17. }
复制代码
实际被代理对象:Tank
  1. package com.gjy.proxy;
  2. public class Tank implements Moveable{
  3.     @Override
  4.      public void move() {
  5.              System.out.println("TanK moving........");
  6.      }
  7.         }
复制代码
测试:
  1. package com.gjy.proxy;
  2.      public class TestTank {
  3.            public static void main(String[] args) {
  4.            Tank t = new Tank();
  5.            Moveable move = new TanktimeProxy(t);
  6.            move.move();
  7.                     }
  8. }
复制代码
从上例可以看到代理主题角色:TanktimeProxy实现了对Tank的move()方法运行时间的计算,而TanktimeProxy,Tank都实现了Moveable接口,通过调用TanktimeProxy的move()方法我们可以实现对Tank的move()方法的运行时间的计算,而不用在Tank的move()方法中作任何实现,这就是代理的作用。代理实现时TanktimeProxy,Tank必需实现Moveable接口。

下面我想在TanK的move()方法前后加上日志:
我必需再写一个类来实现这一功能:
  1. package com.gjy.proxy;
  2. public class TanklogProxy implements Moveable{
  3.         private Moveable t;
  4.         public TanklogProxy(Moveable t) {
  5.                  super();
  6.                  this.t = t;
  7.        }
  8.        @Override
  9.         public void move() {
  10.                   System.out.println("start move........");
  11.                   t.move();
  12.                   System.out.println("end move......");
  13.         }
  14. }
复制代码
测试:
  1. package com.gjy.proxy;
  2. public class TestTank {
  3.           public static void main(String[] args) {
  4.                   Tank t = new Tank();
  5.                   Moveable move = new TanktimeProxy(t);
  6.                   Moveable movet = new TanklogProxy(move);
  7.                   movet.move();
  8.                           }
  9. }
复制代码
这样我通过代理在Tank的move()方法前后加入了日志和时间统计的功能,由于TanktimeProxy,TanklogProxy都实现了Moveable接口,所以TanklogProxy可以代理TanktimeProxy,反过来也可以,它们对Tank的代理顺序是可以交换的。

如果我想在Tank的move()方法调用的前后加入更多的功能,是不是要写更多的代理主题角色,这样子会使得代码过于臃肿,不易于维护,那有没有什么办法可以解决呢,答案是可以的,我们可以动态的来生成代理主题角色,来代理所有的被代理对象,这就是动态代理。

下面是一个简单的动态代理的实现:
类图如下:
[attach]20053[/attach]






c504802d-4a83-39e8-ad27-6d2f9cd99270.png (19.18 KB, 下载次数: 0)

c504802d-4a83-39e8-ad27-6d2f9cd99270.png

作者: 袁梦希    时间: 2013-5-23 17:19
帖子让老曹记录一下,别着急
作者: jinhu358    时间: 2013-5-23 17:31
尹桥印 发表于 2013-5-23 17:09
好东西啊

恩,要分享! 呵呵 
作者: 张林敏    时间: 2013-5-23 22:15
悄悄的给你顶一下......
作者: jinhu358    时间: 2013-5-23 22:20
张林敏 发表于 2013-5-23 22:15
悄悄的给你顶一下......

{:soso_e128:}

作者: GoodBoy123    时间: 2014-7-22 15:54
你的代码好像有点部有问题吧,我编译了发现报错
作者: qiangziwwq    时间: 2014-7-25 08:53
有收获,不错!




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2