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模式

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM