委托代理模式

代理模式是GoF提出的23种设计模式中最为经典的模式之一,代理模式是对象的结构模式,它给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。简单的说,代理对象可以完成比原对象更多的职责,当需要为原对象添加横切关注功能时,就可以使用原对象的代理对象。我们在打开Office系列的Word文档时,如果文档中有插图,当文档刚加载时,文档中的插图都只是一个虚框占位符,等用户真正翻到某页要查看该图片时,才会真正加载这张图,这其实就是对代理模式的使用,代替真正图片的虚框就是一个虚拟代理;Hibernate的load方法也是返回一个虚拟代理对象,等用户真正需要访问对象的属性时,才向数据库发出SQL语句获得真实对象。代理模式的类图如下所示:


下面用一个找枪手代考的例子演示代理模式的使用:

/** 
 * 参考人员接口 
 */  
public interface Candidate {  
      
    /** 
     * 答题 
     */  
    public void answerTheQuestions();  
}  
/** 
 * 懒学生 
 */  
public class LazyStudent implements Candidate {  
    private String name;        // 姓名  
      
    public LazyStudent(String name) {  
        this.name = name;  
    }  
      
    @Override  
    public void answerTheQuestions() {  
        // 懒学生只能写出自己的名字不会答题  
        System.out.println(”姓名: ” + name);  
    }  
} 

/** 
 * 枪手  
 */  
public class Gunman implements Candidate {  
    private Candidate target;   // 被代理对象  
      
    public Gunman(Candidate target) {  
        this.target = target;  
    }  
      
    @Override  
    public void answerTheQuestions() {  
        // 枪手要写上代考的学生的姓名  
        target.answerTheQuestions();  
        // 枪手要帮助懒学生答题并交卷  
        System.out.println(”奋笔疾书正确答案”);  
        System.out.println(”交卷”);  
    }  
}

public class ProxyTest1 {  
  
    public static void main(String[] args) {  
        Candidate c = new Gunman(new LazyStudent(“王小二”));  
        c.answerTheQuestions();  
    }  
}


优点
1.       职责清晰   真实的角色就是实现的业务逻辑,不用关心其他非本指责的事务
2.       高扩展性   具体主题角色不能怎么变化,只要它实现了接口,代理类完全可以在不做任何修改的情况下使用
3.       智能化     动态代理是最好的体现,即在运行阶段才指定实际代理对象(Struts如何把表单元素映射到对象上?)
使用场景   典型应用如Spring AOP面向切面编程技术的底层实现原理也是使用了动态代理模式。
扩展
1.       普通代理    要求客户端只能访问代理角色,而不能访问真实角色
2.       强制代理    要求客户端必须通过真实角色找到代理角色(演员和经纪人)
3.       虚拟代理    指在需要的时候,才初始化主题对象,可以避免被代理对象太多而引起的初始化缓慢问题


动态代理    指在实现阶段不用关心代理谁,而在运行阶段才指定代理哪个对象,动态代理根据被代理的接口生成所有的方法即给定一个接口,动态地理就宣传我已经实现该接口下的所有方法了(通过InvocationHandler接口)
类图:


源码  
1.  接口  
 public interface IGamePlayer {  	
    public void login(String user,String password);  	
    public void killBoss();  	
    public void upgrade();  
 }  
2.  实现类  
 public class GamePlayer implements IGamePlayer {  
    private String name="";  
    public GamePlayer(String _name){  
        this.name=_name;  
    }  
    @Override  
    public void killBoss() {  
        System.out.println(this.name+"在打怪");  
}  
    @Override  
    public void login(String user, String password) {  
        System.out.println("登录名为"+user+"的用户  "+this.name+"登录成功");  
}  
    @Override  
    public void upgrade() {  
        System.out.println(this.name+"又升了一级");  
}  
}  
3.  动态代理类  
 public class GamePlayIH implements InvocationHandler {  
//被代理者  
    Class cls =null;  
    //被代理的实例  
    Object obj=null;  
    //我要代理谁  
    public GamePlayIH(Object _obj){  
        this.obj=_obj;  
    }  
    //调用被代理的方法  
    @Override  
    public Object invoke(Object proxy, Method method, Object[] args)  
            throws Throwable {  
        Object result =method.invoke(this.obj, args);  
        if(method.getName().equalsIgnoreCase("login")){  
            System.out.println("有人登录");  
        }  
        else if(method.getName().equalsIgnoreCase("upgrade")){  
            System.out.println("有人升级了");  
        }  
        return result;                                                                                                             
    }  
}  
4.  场景类  
public class Client {  
    public static void main(String[] args) {  
        IGamePlayer player = new GamePlayer("XXX");  
        InvocationHandler handler = new GamePlayIH(player);  
        System.out.println("开始打游戏,记下时间戳 : "+System.currentTimeMillis());  
        ClassLoader c1=player.getClass().getClassLoader();  
       //动态生成一个代理类  
        IGamePlayer proxy = (IGamePlayer)Proxy.newProxyInstance(c1, new Class[]{IGamePlayer.class}, handler);  
        proxy.login("guojun", "password");  
        proxy.killBoss();  
        proxy.upgrade();  
        System.out.println("结束时间是:"+System.currentTimeMillis());  
    }  
}  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值