一日一摸之第六日 proxy代理模式

     如果创建一个对象需要花费较多的时间,做较多的工作,同时还不确定后面会不会实际用上,如你在超市买手机,就给一个模型给你看就得了,你确定要的时候才去拿一个真机器来给你,这里这个手机模型可以看作是手机的一个代理。还有现在的艺人都会有经纪人,大部分事情你跟他的经纪人联系就搞定了,在登台演出的时候,经纪人自然会安排艺人Live Show。这里经纪人就是艺人的一个Proxy。同时在Proxy这里还可以做一个权限控制,做一层过滤,如在经纪人这里,看你拿不出100W,根本就不会安排艺人演出,艺人也根本就不知道你这个事情,在打印机那里,在打印的时候,也可以做一个权限控制,只有在你具有打印机的操作权限时才会让你打印。权限验证没有通过,打印机对象根本就不会生成。JLive的Forum就使用Proxy进行了权限控制。

 
打印机程序实例,在真正需要打印的时候才生成打印机对象:
/**
  * @(#)Printable.java 1.0 2007 - 10 - 23
  */
package pattern.proxy;
 
/**
  * @author tsimgsong
  *
  */
public interface Printable {
    
     /**
       * Name printer
       * @param name
       */
     public void setPrinterName(String name);
    
     /**
       * get Printer Name
       * @return
       */
     public String getPrinterName();
    
     /**
       *print content
       * @param cnt
       */
     public void print(String cnt);
 
}
 
 
/**
 * @(#)Printer.java 1.0 2007-10-23
 */
package pattern.proxy;
 
import org.apache.log4j.Logger;
 
/**
 * @author tsimgsong
 *
 */
public class Printer implements Printable {
      
       private String name;
      
       static Logger logger = Logger.getLogger(Printer.class);
      
       public Printer(){
              logger.info("Initializing Printer begin ...");
              logger.info("Initialize Printer end ");
       }
      
       public Printer(String name){
              this.name = name;
       }
 
       public String getPrinterName() {
              return name;
       }
 
       public void print(String cnt) {
              logger.info("Print Begin");
              logger.info("Print End");
       }
 
       public void setPrinterName(String name) {
              this.name = name;
       }
 
}
 
/**
 * @(#)PrinterProxy.java 1.0 2007-10-23
*/
package pattern.proxy;
 
/**
 * @author tsimgsong
 *
 */
public class PrinterProxy implements Printable {
       private String name ;
      
       private Printer printer;
 
       public PrinterProxy(){
             
       }
      
       public PrinterProxy(String name){
              this.name = name;
       }
      
       public String getPrinterName() {
              return name;
       }
 
       public void print(String cnt) {
              realPrinter();
              printer.print(cnt);          
       }
 
       public synchronized void setPrinterName(String name) {
              if(printer != null){
                     printer.setPrinterName(name);
              }
              this.name = name;
       }
      
       private synchronized void realPrinter(){
              if(printer == null){
                     printer = new Printer(name);
              }           
       }
}
如对打印机的使用进行权限控制,就不要客户端直接生成Printer对象,要打印都通过PrinterProxy来打印,在打印的地方对客户端权限进行判定。
public void print(PrintPermission permission,String cnt) throws PrintException, UnauthorizedException {
    if(permission.canPrint()){
              realPrinter();
              printer.print(cnt);          
}else{
        Throw new UnauthorizedException();
}
}
 
使用Java提供的动态代理:(JAVA提供了一个Proxy类和一个InvocationHandler,这两个类都在java.lang.reflect包中。程序员通过实现java.lang.reflect.InvocationHandler接口提供一个执行处理器,然后通过java.lang.reflect.Proxy得到一个代理对象,通过这个代理对象来执行方法,方法被调用的同时,执行处理器会被自动调用。)
package pattern.proxy;
 
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
 
/**
  * @author tsimgsong
  *
  */
public class DynamicProxy  implements InvocationHandler{
    
     private Object original ;
    
     public DynamicProxy(Object orig){
         this . original = orig;
     }
 
     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 这里可以加上权限控制
         Object obj = method.invoke( original , args);
         return obj;
     }
    
     public static void main(String args[]){
         Printer pp = new Printer();
         DynamicProxy dp = new DynamicProxy(pp);
         Printable p = (Printable)Proxy.newProxyInstance(DynamicProxy. class .getClassLoader(), new Class[]{Printable. class }, dp);
         p.print( "ddddd" ); }
}
程序首先创建一个被代理对象然后初始化代理对象,最后由Proxy的newProxyInstance获得一个代理实例, newProxyInstance方法有三个参数, ClassLoader, Class[] interfaces, InvocationHandler。ClassLoader是当前的类加载器,interfaces是代理实例要实现的接口的类(需要指出java的Proxy是针对接口的,如果传入的Class类型不是接口,会抛出IllegalArgumentException异常)。InvocationHandler则是我们写的代理处理器。newProxyInstance获得的实例对象的类是通过修改java二进制文件来获得的,Proxy中有一个private static native Class defineClass0(ClassLoader loader, String name,byte[] b, int off, int len);方法,这个本地方法实现了这个Class的生成,至于具体的实现我们无法看到,不过很多资料上都有关于native方法的讨论。
 
Ref:
2、 http://boool.blogdriver.com/boool/284115.html
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值