代理模式

转自:

http://www.iteye.com/topic/517835

 

代理模式:给某一对象提供代理对象,并由代理对象控制具体对象的引用. 

代理,指的就是一个角色代表另一个角色采取行动,就象生活中,一个红酒厂商,是不会直接把红酒零售客户的,都是通过代理来完成他的销售业务的.而客户,也不用为了喝红酒而到处找工厂,他只要找到厂商在当地的代理就行了,具体红酒工厂在那里,客户不用关心,代理会帮他处理. 

代理模式涉及的角色: 
1:抽象主题角色.声明了代理主题和真实主题的公共接口,使任何需要真实主题的地方都能用代理主题代替. 

2:代理主题角色.含有真实主题的引用,从而可以在任何时候操作真实主题,代理主题功过提供和真实主题相同的接口,使它可以随时代替真实主题.代理主题通过持有真实主题的引用,不但可以控制真实主题的创建或删除,可以在真实主题被调用前进行拦截,或在调用后进行某些操作. 

3:真实代理对象.定义了代理角色所代表的具体对象. 

下面是代理模式的实现类图: 
 

根据上图的关系,我们可以用客户买红酒来模拟代理模式的实现, 

红酒代理商和红酒厂商都有销售红酒的只能,我们可以为他们定义一个共同的抽象主题角色, 

Java代码    收藏代码
  1. /** 
  2. *抽象主题角色,定义了真实角色和代理角色的公共接口 
  3. */  
  4. public interface SellInterface{  
  5.      public Object sell();  
  6. }  



接着,我们定义真实主题角色(这里就是红酒工厂),它必须实现了SellInterface接口的.

Java代码    收藏代码
  1. /** 
  2. *真实主题角色,这里指红酒工厂角色,它实现了SellInterface接口 
  3. */  
  4. public class RedWineFactory implements SellInterface{  
  5.      public Object sell(){  
  6.          System.out.println("真实主题角色RedWineFactory 被调用了");  
  7.          return new Object();  
  8.      }  
  9. }  



下面是代理主题角色(这里指红酒代理商),同样,代理主题也必须实现SellInterface接口.

Java代码    收藏代码
  1. /** 
  2. *代理主题角色,这里指红酒代理商.它除了也要实现了sellInterface接口外,还持有红酒 
  3. *厂商RedWineFactory 对象的引用,从而使它能在调用真实主题前后做一些必要处理. 
  4. */  
  5. public class RedWineProxy implements SellInterface{  
  6.      //持有一个RedWineFactory对象的引用  
  7.       private RedWineFactory redWineFactory;  
  8.   
  9.      //销售总量  
  10.       private static int sell_count = 0;  
  11.   
  12.      public Object sell(){  
  13.          if(checkUser()){//在通过代理主题角色,我们可以在真实主题角色被调用前做一些诸如权限判断的事情  
  14.              Object obj = redWineFactory.sell();  
  15.              count ++;//同样,在调用后我们也可以执行一些额外的动作.  
  16.              return obj ;  
  17.          }else{  
  18.              throw new RuntimeException();  
  19.          }  
  20.      }  
  21.   
  22.      protected boolean checkUser(){  
  23.             //do something  
  24.             return true;  
  25.      }  
  26. }  



接下来看看调用代理对象的代码

Java代码    收藏代码
  1. public static void main(String agr[])  
  2. {  
  3.      SellInterface sell = new RedWineProxy();  
  4.      sell.sell();  
  5. }  



从上面的例子可以看出代理模式的工作方式,首先,因为代理主题和真实主题都实现了共同的接口,这使我们可以在不改变原来接口的情况下,只要用真实主题对象的地方,都可以用代理主题来代替.其次,代理主题在客户和真实主题之间起了一个中介作用,利用这个中介平台,我们可以在把客户请求传递给真实主题之前,做一些必要的预处理. 

java对代理模式的支持 ---动态代理 
上面的代理,我们强迫代理类RedWineProxy实现了抽象接口SellInterface.这导致我们的代理类无法通用于其他接口,所以不得不为每一个接口实现一个代理类.幸好,java为代理模式提供了支持. 
java主要是通过Proxy类和InvocationHandler接口来给实现对代理模式的支持的. 
下面用java的代理机制来实现上面的例子

Java代码    收藏代码
  1. import java.lang.reflect.InvocationHandler;  
  2. import java.lang.reflect.Method;  
  3. import java.lang.reflect.Proxy;  
  4. /** 
  5. *代理类一定要实现了InvocationHandler接口 
  6. */  
  7. public class ProxyObject implements InvocationHandler{  
  8.     private Object proxy_obj;  
  9.   
  10.     ProxyObject(Object obj){  
  11.         this.proxy_obj = obj;  
  12.     }  
  13.   
  14.     public static Object factory(Object obj){  
  15.         Class cls = obj.getClass();  
  16.         //通过Proxy类的newProxyInstance方法来返回代理对象  
  17.         return Proxy.newProxyInstance(cls.getClassLoader(), cls.getInterfaces(),new ProxyObject(obj));  
  18.     }  
  19.   
  20. /** 
  21. *实现InvocationHandler接口的invoke 
  22. */  
  23.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
  24.         System.out.println("函数调用前被拦截了:   " + method);  
  25.         if(args != null){  
  26.             //打印参数列表  
  27.             System.out.println("方法有  " + args.length + "    个参数");  
  28.             for(int i = 0; i < args.length; i ++){  
  29.                 System.out.println(args[i]);  
  30.             }  
  31.         }  
  32.         //利用反射机制动态调用原对象的方法  
  33.          Object mo = method.invoke(proxy_obj, args);  
  34.         System.out.println("函数调用后进行处理 :   " + method);  
  35.         return mo;  
  36.     }  
  37.   
  38.     //测试代码      
  39.     public static void main(String agr[]){  
  40.         SellInterface si = (SellInterface)factory(new RedWineFactory());  
  41.         si.sell();  
  42.     }  
  43. }  


通过上面的代码可以看出,代理主题ProxyObject类并没有实现我们定义的SellInterface借口, 
而是实现了java的InvocationHandler接口,这样就把代理主题角色和我们的业务代码分离开来,使代理对象能通用于其他接口. 
其实InvocationHandler接口就是一种拦截机制,当系统中有了代理对象以后,对原对象(真实主题)方法的调用,都会转由InvocationHandler接口来处理,并把方法信息以参数的形式传递给invoke方法,这样,我们就可以在invoke方法中拦截原对象的调用,并通过反射机制来动态调用原对象的方法.这好象也是spring aop编程的基础吧 

接着,用代理模式实现一个超级简单的aop拦截机制 
这个例子可以拦截我们指定的函数,并在拦截前后根据需要进行处理

Java代码    收藏代码
  1. /** 
  2. *切面接口,通过实现这个接口,我们可以对指定函数在调用前后进行处理 
  3. */  
  4. public interface AopInterface {  
  5.    public void before(Object obj);//调用的处理  
  6.    public void end(Object obj);//调用后的处理  
  7. }  



这个是实现了AopInterface 接口,在这里我们实现了我们的处理逻辑

Java代码    收藏代码
  1. public class AopInterfaceImp implements AopInterface{  
  2.   
  3.     public void before(Object obj) {  
  4.         System.out.println("调用前拦截");  
  5.     }  
  6.   
  7.     public void end(Object obj) {  
  8.         System.out.println("调用调用后处理");  
  9.     }  
  10.   
  11. }  


。。。内容太长,请大家到原文链接去看。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值