Android-笔记 关于代理模式的解析

关于代理模式的解析

在说代理之前,先说一下反射。 什么是反射就不说了,我就说一下应用场景,因为反射不纠结其原理,那真的就是api的调用了,这里我只是做个笔记。反射在各大框架里面应用的很广泛,比如我们常用的Retrofit,其中有一个方法create(),我们需要传入自己申明的API接口。这里就是典型的反射应用场景,通过反射拿到我们的api类对象,再通过这个类对象找到对应的方法。再看看如下代码,应该有点儿体会吧,是不是你的代码里有些地方就可以用到这个。还想了解多一点的话,可以参考一下这个java高级特性—反射

                Class dialog = Class.forName("com.***.BaseDialogFragment");
                Field mHandler = dialog.getDeclaredField("mHandler");
                mHandler.setAccessible(true);//允许访问私有对象
                Class handlerClass = Class.forName(mHandler.getType().getName());
                Method handlerMethod = handlerClass.getDeclaredMethod("removeCallbacksAndMessages", Object.class);
                handlerMethod.setAccessible(true);
                handlerMethod.invoke(mHandler.get(this), (Object) null);//指明是哪个对象调用removeCallbacksAndMessages的方法
                LogUtil.e("This dialog has destroyed!");

何为代理模式

一句话,给目标对象提供一个代理对象,并由代理对象控制对目标对象的访问。来来看下面这个草图,是不是就有点儿意思了。代理模式又分为静态代理和动态代理,其实静态代理应用的不多(因为违反了开闭原则),动态代理才是主流。再往下看看代码,你就一目了然了。
在这里插入图片描述
为啥要用代理模式呢?因为代理模式十分符合java开发的封闭开放原则,避免大幅度修改原先的代码,只是在原有的基础上进行拓展。笼统的来说,就是下面俩点:

  • 通过引入代理对象的方式来间接访问目标对象,防止直接访问目标对象给系统带来的不必要复杂性
  • 通过代理对象可以对原有的业务进行拓展

大家可以看看以这个类图,又是一目了然:
在这里插入图片描述

.

静态代理的相关用法

接口申明相关操作,代理对象和目标对象都实现这个接口,然后代理对象调用目标对象的方法,在目标对象的方法调用之前和调用之后可以进行拓展,我写了一个简单的demo ,可以参考一下:


/**
 * @Author: Ryan
 * @Date: 2020/6/11 16:04
 * @Description: java类作用描述
 */
public interface Selling {
    void sellSomething();
}

目标对象:

/**
 * @Author: Ryan
 * @Date: 2020/6/11 16:07
 * @Description: 目标对象
 */
public class RealObject implements Selling {
    @Override
    public void sellSomething() {
        System.out.println("一条18块的利群");
    }
}

代理对象:

/**
 * @Author: Ryan
 * @Date: 2020/6/11 16:06
 * @Description: 代理对象
 */
public class RyanObject implements Selling {
    private Selling selling;

    public RyanObject(Selling selling) {
        this.selling = selling;
    }//传入目标对象

    //代理对象可以对目标对象进行的业务拓展
    private void extraService1() {
        System.out.println("喊你一声靓仔");
    }

    //代理对象可以对目标对象进行的业务拓展
    private void extraService2() {
        System.out.println("提供美女收银员的微信");
    }
    @Override
    public void sellSomething() {
        extraService1();
        selling.sellSomething();
        extraService2();
    }
}

调用方法:

/**
 * @Author: Ryan
 * @Date: 2020/6/11 16:17
 * @Description: 测试输出类
 */
public class TestClient {

    public static void main(String[] args) {
        /*-------------静态代理模式-------------*/
        Selling selling = new RealObject();//实现接口的方法,
        RyanObject ryanObject = new RyanObject(selling);//将目标对象的业务传给代理对象,同时代理对象内部可以对其做扩展
        ryanObject.sellSomething();

        /*-------------动 态代理模式-------------*/
    }
}

总结:前面提到了今天代理违反了设计模式的开闭原则,这里解释一下。打个比方,现在又来了一个顾客他想买RIO鸡尾酒,代理对象是不是现在不能满足这个需求,是不是只有扩展目标对象,代理对象才可以有RIO卖,这样一来一共就那么几个文件,全得修改一遍,那要是人家想买一堆杂七杂八的,可想而知。。。。。

动态代理的相关用法

动态代理有俩个关键的字段,一个是proxy,一个是invocationHandler,前者你可以理解为是是通过这个proxy获取到动态代理对象,后者则可以理解成拓展的需求服务啥啥的。

动态生成代理对象:


/**
 * @Author: Ryan
 * @Date: 2020/6/11 17:36
 * @Description: 动态生成代理对象
 */
public class ActiveRealObject implements InvocationHandler {
    private Object realObject;

    public Object getRealObject() {
        return realObject;
    }

    public void setRealObject(Object realObject) {
        this.realObject = realObject;
    }

    //代理对象的方法可以对目标对象进行的业务拓展
    private void extraService1() {
        System.out.println("喊你一声靓仔");
    }

    //代理对象的方法可以对目标对象进行的业务拓展
    private void extraService2() {
        System.out.println("提供美女收银员的微信");
    }

    public Object getProxyInstance() {//利用poxy通过反射获取到动态代理对象
        return Proxy.newProxyInstance(realObject.getClass().getClassLoader(), realObject.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//这里就是对原先的业务拓展
        extraService1();
        Object object = method.invoke(realObject, args);//通过反射,调用了目标
        extraService2();
        return object;
    }
}

调用方法:


/**
 * @Author: Ryan
 * @Date: 2020/6/11 16:17
 * @Description: 测试输出类
 */
public class TestClient {

    public static void main(String[] args) {
//        /*-------------静态代理模式-------------*/
//        Selling selling = new RealObject();//实现接口的方法,
//        RyanObject ryanObject = new RyanObject(selling);//将目标对象的业务传给代理对象,同时代理对象内部可以对其做扩展
//        ryanObject.sellSomething();

        /*-------------动态代理模式-------------*/
        Selling selling1 = new RealObject();
        ActiveRealObject activeRealObject = new ActiveRealObject();
        activeRealObject.setRealObject(selling1);//设置代理对象的代理目标
        Selling proxy = (Selling) activeRealObject.getProxyInstance();
        proxy.sellSomething();

        Recycling recycling=new RealObject2();
        ActiveRealObject activeRealObject2 = new ActiveRealObject();
        activeRealObject2.setRealObject(recycling);//设置代理对象的代理目标
        Recycling proxy2= (Recycling) activeRealObject2.getProxyInstance();
        proxy2.recycleSomething();
    }
}

总结:

  • 接口申明需求
  • 目标对象实现接口
  • 实现iinvocationHandler接口,动态生成代理对象,生成代理对象过程中可以扩展需求
    前俩步动态代理和静态代理是一致的,区别就在于第三步,很明显第三步能适应多样化的需求,拓展性更高,但是内部实现的时候用到了java的反射,所以动态代理的性能要逊色于静态代理的。。。。。先比比这么多,下班了!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值