• Android中的代理模式


    代理的概念:为某个对象提供一个代理,以控制对这个对象的访问。 代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代。代理类负责请求的预处理、过滤、将请求分派给委托类处理、以及委托类执行完请求后的后续处理。
    
    
        抽象对象角色:就是代理类和委托类共同的接口,声明了目标对象和代理对象的共同接口,这样一来在任何可以使用目标对象的地方都可以使用代理对象。
        目标对象角色:就是委托类,定义了代理对象所代表的目标对象。
        代理对象角色:就是代理类,代理对象内部含有目标对象的引用,从而可以在任何时候操作目标对象;代理对象提供一个与目标对象相同的接口,以便可以在任何时候替代目标对象。代理对象通常在客户端调用传递给目标对象之前或之后,执行某个操作,而不是单纯地将调用传递给目标对象。
    
    静态代理
    代理类在程序运行前已经存在的代理方式称为静态代理。
    
        /**
         * 定义Demo接口
         */
        public interface Demo {  
            public void save();
        }
    
        /**
         * DemoImpl实现Demo接口并覆写save()方法
         * 真实主题,执行具体业务
         */
        public class DemoImpl implements Demo {  
            public void save() {
                System.out.println("调用save()方法");
            }
        }
    
        /**
         * DemoImplProxy 也实现了Demo接口,并覆写了save()方法,增加了自己的业务 
         * 代理主题,负责其他业务的处理
         */
        public class DemoImplProxy implements Demo {  
            Demo demoImpl = new DemoImpl();
         
            public void save() {
                System.out.println("开始记录日志");
                demoImpl.save();
                System.out.println("开始结束日志");
            }
        }
    
    静态代理有一个缺点,每个代理类只能为一个接口服务,这样程序开发中必然会产生许多的代理类。
    动态代理
    代理类在程序运行前不存在、运行时由程序动态生成的代理方式称为动态代理。
    实现动态代理包括三步:
    
    (1). 新建代理类和委托类共同的接口以及委托类;
    (2). 实现InvocationHandler接口,这是负责连接代理类和委托类的中间类必须实现的接口;
    (3). 通过Proxy类新建代理类对象。
    
    第一步:新建代理类和委托类共同的接口以及委托类
    
        public interface Operate {
         
            public void operateMethod1();
         
            public void operateMethod2();
         
            public void operateMethod3();
        }
    
        public class OperateImpl implements Operate {
         
            @Override
            public void operateMethod1() {
                System.out.println("Invoke operateMethod1");
                sleep(110);
            }
         
            @Override
            public void operateMethod2() {
                System.out.println("Invoke operateMethod2");
                sleep(120);
            }
         
            @Override
            public void operateMethod3() {
                System.out.println("Invoke operateMethod3");
                sleep(130);
            }
         
            private static void sleep(long millSeconds) {
                try {
                    Thread.sleep(millSeconds);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
    
    第二步:实现InvocationHandler接口
    
    java.lang.reflect.InvocationHandler接口的定义如下:
    
        /**
        *
        *Object proxy:被代理的对象
        *Method method:要调用的方法
        *Object[] args:方法调用时所需要参数
        */
        public interface InvocationHandler {  
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
        }
    
    实现 InvocationHandler 接口
    
        public class TimingInvocationHandler implements InvocationHandler {
         
            private Object target;
            public TimingInvocationHandler() {}
            public TimingInvocationHandler(Object target) {
                this.target = target;
            }
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                long start = System.currentTimeMillis();
                Object obj = method.invoke(target, args);
                System.out.println(method.getName() + " cost time is:" + (System.currentTimeMillis() - start));
                return obj;
            }
        }
    
    第三步:通过Proxy类新建代理类对象
    
    java.lang.reflect.Proxy类的定义如下:
    
        /**
        *CLassLoader loader:类的加载器
        *Class<?> interfaces:得到全部的接口
        *InvocationHandler h:得到InvocationHandler接口的子类的实例
        */
        public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException  
    
        public class Main {
            public static void main(String[] args) {
                // create proxy instance
                TimingInvocationHandler timingInvocationHandler = new TimingInvocationHandler(new OperateImpl());
                Operate operate = (Operate)(Proxy.newProxyInstance(Operate.class.getClassLoader(), new Class[] {Operate.class},
                        timingInvocationHandler));
         
                // call method of proxy instance
                operate.operateMethod1();
                System.out.println();
                operate.operateMethod2();
                System.out.println();
                operate.operateMethod3();
            }
        }
    
    
    下面总结一下动态代理对象创建过程
    
        // InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发
        // 其内部通常包含指向委托类实例的引用,用于真正执行分派转发过来的方法调用
        InvocationHandler handler = new InvocationHandlerImpl(..); 
         
        // 通过 Proxy 为包括 Interface 接口在内的一组接口动态创建代理类的类对象
        Class clazz = Proxy.getProxyClass(classLoader, new Class[] { Interface.class, ... }); 
         
        // 通过反射从生成的类对象获得构造函数对象
        Constructor constructor = clazz.getConstructor(new Class[] { InvocationHandler.class }); 
         
        // 通过构造函数对象创建动态代理类实例
        Interface Proxy = (Interface)constructor.newInstance(new Object[] { handler });
    
    
    从上面可以看到,实际使用过程更加简单,因为 Proxy 的静态方法 newProxyInstance 已经为我们封装了步骤 2 到步骤 4 的过程,所以简化后的过程如下
    
        // InvocationHandlerImpl 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发
        InvocationHandler handler = new InvocationHandlerImpl(..); 
         
        // 通过 Proxy 直接创建动态代理类实例
        Interface proxy = (Interface)Proxy.newProxyInstance( classLoader, 
             new Class[] { Interface.class }, 
             handler );
    
    
    参考文章:
    
    Java 动态代理机制分析
    
    公共技术点之 Java 动态代理
    
    代理模式和android插件化
    
    Android设计模式源码解析之Proxy模式
  • 相关阅读:
    Vue--vue-Router
    Vue--vue中的组件、组件绑定事件和数据、私有组件、子组件,父子组件参数互传
    CF 631C report
    生日Party 玄学多维DP
    HDU-6376 度度熊剪纸条
    CF 1012C Dp
    CF 997A
    HDU-1051 一个DP问题
    偶尔间看到,来开心一下
    合并石子
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/10401464.html
Copyright © 2020-2023  润新知