Java设计模式之代理模式(Proxy) - 总李写代码 - 博客园

380 阅读12分钟
原文链接: www.cnblogs.com
总李写代码
干我们这行,啥时候懈怠,就意味着长进的停止,长进的停止就意味着被淘汰,只能往前冲,直到凤凰涅槃的一天! 博客园     新随笔       管理 随笔-126  评论-286  文章-0 

Java设计模式之代理模式(Proxy)

前言:

      最近在研究Retrofit开源框架的时候,其主要核心代码是通过注解标示参数,动态代理模式实现具体接口,反射机制进行参数解析,最终实现发送请求。其实之前在学习Xutils源码的时候,Xutils 的task也是通过代理模式来访问的。为何要采用代理模式呢?有什么好处呢?抱着这些疑问!今天来学习总结一下。

 什么是代理模式?

       代理模式的定义:代理模式给某一个对象提供一个代理对象,并由代理对象控制对原对象的引用。举例说明,就是一个人或者一个机构代表另一个人或者另一个机构采取行动。在一些情况下,一个客户不想或者不能够直接引用一个对象,而代理对象可以在客户端和目标对象之前起到中介的作用。

应用场景举例:

       通过上面的代理模式描述我们可以知道,其目的就是为了控制对象引用,生活场景中我们以买车为例,如果我们要买一辆轿车必须通过汽车4S店,汽车4s店就是充当代理角色,其目的就是控制买车客户的买车行为,必须通过汽车4S店才能从汽车厂商买一辆车。

1.)首先新建一个买车的接口

public interface IBuyCar {
    //买车
    void buyCar();
}

2.)声明一个要买车的客户,实现买车接口

public class Customer implements IBuyCar {

    private int cash;//购车款

    public int getCash() {
        return cash;
    }

    public void setCash(int cash) {
        this.cash = cash;
    }

    @Override
    public void buyCar() {
        Log.e("buyCar", "买一辆车花费了-->" + cash + "元");
    }
}

3.)声明一个买车代理汽车4S店,同样也实现买车接口,必须接受客户下单

public class BuyCarProxy implements IBuyCar{
    private Customer customer;//接收买车客户

    public BuyCarProxy(Customer customer){
        this.customer=customer;//接收买车客户
    }

    @Override
    public void buyCar() {//实现为客户买车
        customer.buyCar();
    }
}

4.)创建一个客户端,模拟一次买车

  Customer customer=new Customer();
  customer.setCash(120000);
  BuyCarProxy buyCarProxy=new BuyCarProxy(customer);
  buyCarProxy.buyCar();

5.)通过代理模式实现权限控制

  通过上面的例子,我们可能有个疑问,难道就不能直接去厂家买车吗?当然可以,如果在使用场景中实现类能满足要求时,我们当然可以直接实现类,但当实现类不能满足要求,要扩展需求,根据开闭原则你又不能修改实现类代码,这时你就用代理类。比如购买一辆车我们要对客户进行一个购车款审核,如果符合条件就买车,不符合要求我们就告知客户购车款不足。

 @Override
    public void buyCar() {//实现为客户买车
        int cash=customer.getCash();
        if(cash<100000){
            Log.e("buyCar","你的钱不够买一辆车");
            return;
        }
        customer.buyCar();
    }

实现场景

Customer customer=new Customer();
customer.setCash(120000);
BuyCarProxy buyCarProxy=new BuyCarProxy(customer);
buyCarProxy.buyCar();

Customer customer1 =new Customer();
customer1.setCash(90000);
BuyCarProxy buyCarProxy1 =new BuyCarProxy(customer1);
buyCarProxy1.buyCar();

动态代理机制:

以上讲的都是代理模式的静态实现,所谓静态代理就是自己要为要代理的类写一个代理类,或者用工具为其生成的代理类,总之,就是程序运行前就已经存在的编译好的代理类,这样有时候会觉得非常麻烦,也导致非常的不灵活,相比静态代理,动态代理具有更强的灵活性,因为它不用在我们设计实现的时候就指定某一个代理类来代理哪一个被代理对象,我们可以把这种指定延迟到程序运行时由JVM来实现。

举例:还是接着上面的例子

1.)首先我们要声明一个动态代理类,实现InvocationHandler接口

public class DynamicProxy implements InvocationHandler {

    // 被代理类的实例
    Object obj;

    // 将被代理者的实例传进动态代理类的构造函数中
    public DynamicProxy(Object obj) {
        this.obj = obj;
    }

    /**
     * 覆盖InvocationHandler接口中的invoke()方法
     * 更重要的是,动态代理模式可以使得我们在不改变原来已有的代码结构
     * 的情况下,对原来的“真实方法”进行扩展、增强其功能,并且可以达到
     * 控制被代理对象的行为,下面的before、after就是我们可以进行特殊
     * 代码切入的扩展点了。
     */
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        /*
         * before :doSomething();
         */
        Object result = method.invoke(this.obj, args);

        /*
         * after : doSomething();
         */
        return result;
    }
}

2.)具体实现

        //我们要代理的真实对象
        Customer customer = new Customer();
        //我们要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法的
        InvocationHandler handler = new DynamicProxy(customer);

        /*
         * 通过Proxy的newProxyInstance方法来创建我们的代理对象,我们来看看其三个参数
         * 第一个参数 handler.getClass().getClassLoader() ,我们这里使用handler这个类的ClassLoader对象来加载我们的代理对象
         * 第二个参数customer.getClass().getInterfaces(),我们这里为代理对象提供的接口是真实对象所实行的接口,表示我要代理的是该真实对象,这样我就能调用这组接口中的方法了
         * 第三个参数handler, 我们这里将这个代理对象关联到了上方的 InvocationHandler 这个对象上
         */
        IBuyCar buyCar = (IBuyCar) Proxy.newProxyInstance(handler.getClass().getClassLoader(), customer.getClass().getInterfaces(), handler);
        buyCar.buyCar();

3.)动态代理好处

使用Java动态代理机制的好处:

1、减少编程的工作量:假如需要实现多种代理处理逻辑,只要写多个代理处理器就可以了,无需每种方式都写一个代理类。

2、系统扩展性和维护性增强,程序修改起来也方便多了(一般只要改代理处理器类就行了)。

总结:

   通过上面的应用例子我们学习了代理模式的具体使用场景。

干我们这行,啥时候懈怠,就意味着长进的停止,长进的停止就意味着被淘汰,只能往前冲,直到凤凰涅槃的一天! posted on 2016-07-22 10:50 总李写代码 阅读(16545) 评论(2) 编辑 收藏
评论: #1楼 2018-04-27 17:33 | frankie0802  
假如需要实现多种代理处理逻辑,只要写多个代理处理器就可以了
请问怎么写多个代理处理器呢?谢谢了 支持(0)反对(0)   #2楼 39692442018/5/7 16:38:03 2018-05-07 16:38 | uidoer  
@ frankie0802
?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 /* DynamicProxy : 动态代理类名。   如果你想另外第一个别的动态代理类去做别的事情,同样地,也必须要实现InvocationHandler 接口。 */   public class DynamicProxy implements InvocationHandler {   // 被代理类的实例 Object obj;   // 将被代理者的实例传进动态代理类的构造函数中 public DynamicProxy(Object obj) { this.obj = obj; }   /** * 覆盖InvocationHandler接口中的invoke()方法 * 更重要的是,动态代理模式可以使得我们在不改变原来已有的代码结构 * 的情况下,对原来的“真实方法”进行扩展、增强其功能,并且可以达到 * 控制被代理对象的行为,下面的before、after就是我们可以进行特殊 * 代码切入的扩展点了。 */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { /* * before :doSomething(); //动态代理类为目标类额外做的前置方法 * 可以是简单的sysout。也可以是你具体的方法 */ Object result = method.invoke(this.obj, args);   /* * after : doSomething(); //动态代理类为目标类额外做的后置方法 * 可以是简单的sysout。也可以是你具体的方法 */ return result; } }
支持(0)反对(0) http://pic.cnblogs.com/face/1075715/20161209234217.png   刷新评论刷新页面返回顶部 注册用户登录后才能发表评论,请 登录注册访问网站首页。 【推荐】超50万VC++源码: 大型组态工控、电力仿真CAD与GIS源码库!
【前端】SpreadJS表格控件,可嵌入应用开发的在线Excel
【推荐】如何快速搭建人工智能应用?
【活动】AI技术全面场景化落地实践
【大赛】2018首届“顶天立地”AI开发者大赛
腾讯云0710 最新IT新闻:
· Google Photos面部识别功能获更新:将同个人照片整合至一个组
· Facebook最大的问题是什么?高管们都不会说话
· 爱钱帮出借合同曝疑点:陆复斌、张培峰唱“双簧”?
· NASA下周五公布执行SpaceX及波音太空载人飞行任务宇航员名单
· Python之父透露退位隐情,与核心开发团队产生隔阂
» 更多新闻... 最新知识库文章:
· 历史转折中的“杭派工程师”
· 如何提高代码质量?
· 在腾讯的八年,我的职业思考
· 为什么我离开了管理岗位
· 那些让人睡不着觉的bug,你有没有遭遇过?
» 更多知识库文章... 昵称:总李写代码
园龄:2年2个月
粉丝: 365
关注:0 +加关注

最新随笔

随笔分类(126)

积分与排名

  • 积分 - 274375
  • 排名 - 780

最新评论

阅读排行榜

推荐排行榜

Powered by: 博客园 模板提供:沪江博客 Copyright ©2018 总李写代码