代理設(shè)計模式在Android開發(fā)中的應(yīng)用

1. 模式定義

為其他對象提供一種代理以控制對這個對象的訪問,分為靜態(tài)代理和動態(tài)代理,代理模式也被稱為委托模式,它是結(jié)構(gòu)型設(shè)計模式的一種。在現(xiàn)實生活中我們用到類似代理模式的場景有很多,比如代理上網(wǎng)、打官司等。編程的思想其實有的時候和生活差不多。

2. 代理模式的差異

靜態(tài)代理,在代碼運行前就已經(jīng)存在了代理類的class編譯文件;而動態(tài)代理則是在代碼運行時通過反射來動態(tài)地生成代理類的對象,并確定到底來代理誰。也就是我們在編碼階段無須知道代理誰,代理誰將會在代碼運行時決定。

在我們?nèi)粘i_發(fā)中,有一些類似于功能入口的列表,每個按鈕跳轉(zhuǎn)到不同的頁面,下面我們以頁面跳轉(zhuǎn)為例,用代理設(shè)計模式進行講解。

3. 靜態(tài)代理

IItemClick:提供跳轉(zhuǎn)到各個頁面的方法 的接口

/**
 * 提供跳轉(zhuǎn)到各個頁面的方法 的接口
 */
public interface IItemClick {
    void goToMain();
    void goToDetail();
}

ButtonList:需要被代理跳轉(zhuǎn)操作的類

/**
 * 需要被代理跳轉(zhuǎn)操作的類
 */
public class ButtonList implements IItemClick {

    private int clickPosition;

    public void setClickPosition(int clickPosition) {
        this.clickPosition = clickPosition;
    }

    public int getClickPosition() {
        return clickPosition;
    }

    @Override
    public void goToMain() {
        // 跳轉(zhuǎn)到首頁
    }

    @Override
    public void goToDetail() {
        // 跳轉(zhuǎn)到詳情頁
    }
}

JumpStaticProxy:跳轉(zhuǎn)事務(wù)靜態(tài)代理類

/**
 * 跳轉(zhuǎn)事務(wù)代理類
 */
public class JumpStaticProxy implements IItemClick {

    private IItemClick iItemClick;

    public JumpStaticProxy(@NonNull IItemClick iItemClick) {
        this.iItemClick = iItemClick;
    }

    @Override
    public void goToMain() {
        iItemClick.goToMain();
    }

    @Override
    public void goToDetail() {
        iItemClick.goToDetail();
    }
}

StaticProxyTestClient:用法,測試類

/**
 * 測試類
 */
public class StaticProxyTestClient {

    public static void main(String[] args){
        ButtonList buttonList = new ButtonList();
        JumpStaticProxy jumpStaticProxy = new JumpStaticProxy(buttonList);
        if (buttonList.getClickPosition() == 0) {
            jumpStaticProxy.goToMain();
        } else if (buttonList.getClickPosition() == 1) {
            jumpStaticProxy.goToDetail();
        }
    }
}
4. 動態(tài)代理

假設(shè)這時候,我們在列表中增加了一個按鈕,是跳轉(zhuǎn)到設(shè)置頁,那么要是在靜態(tài)代理的寫法需要同時改動 IItemClick、ButtonList、JumpStaticProxy,這樣的拓展性不高,那用動態(tài)代理怎樣寫呢?Java 提供了 動態(tài)的代理接口 InvocationHandler,實現(xiàn)該接口需要重寫invoke() 方法。

IItemClick:提供跳轉(zhuǎn)到各個頁面的方法 的接口

/**
 * 提供跳轉(zhuǎn)到各個頁面的方法 的接口
 */
public interface IItemClick {
    void goToMain();
    void goToDetail();
    // 增加的方法
    void goToSetting();
}

ButtonList:需要被代理跳轉(zhuǎn)操作的類

/**
 * 需要被代理跳轉(zhuǎn)操作的類
 */
public class ButtonList implements IItemClick {

    private int clickPosition;

    public void setClickPosition(int clickPosition) {
        this.clickPosition = clickPosition;
    }

    public int getClickPosition() {
        return clickPosition;
    }

    @Override
    public void goToMain() {
        // 跳轉(zhuǎn)到首頁
    }

    @Override
    public void goToDetail() {
        // 跳轉(zhuǎn)到詳情頁
    }

    @Override
    public void goToSetting() {
        // 跳轉(zhuǎn)到設(shè)置頁
    }
}

JumpDynamicProxy:核心類,跳轉(zhuǎn)事務(wù)動態(tài)代理類

/**
 * 跳轉(zhuǎn)事務(wù)動態(tài)代理類
 */
public class JumpDynamicProxy implements InvocationHandler {
    /**
     * 被代理的對象
     */
    private Object mObject;

    public JumpDynamicProxy(Object object) {
        this.mObject = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 執(zhí)行方法 ,目標接口調(diào)用的方法都會來到這里面
        // 調(diào)用被代理對象的方法
        Object object = method.invoke(mObject, args);
        return object;
    }
}

DynamicProxyTestClient:動態(tài)代理用法介紹

public class DynamicProxyTestClient {
    public static void main(String[] args) {
        ButtonList buttonList = new ButtonList();

        IItemClick itemClick =
                // 返回的是 IBank 的一個實例對象,這個對象是由 Java 給我們創(chuàng)建的 ,調(diào)用的是 jni
                (IItemClick) Proxy.newProxyInstance(
                        IItemClick.class.getClassLoader(), // ClassLoader
                        new Class<?>[]{IItemClick.class},  // 目標接口
                        new JumpDynamicProxy(buttonList)   // JumpDynamicProxy (這個類是關(guān)鍵)
                );
        if (buttonList.getClickPosition() == 0) {
            itemClick.goToMain();
        } else if (buttonList.getClickPosition() == 1) {
            itemClick.goToDetail();
        } else {
            itemClick.goToSetting();
        }
    }
}
5. 總結(jié)

從上面可以看出,動態(tài)代理的拓展性優(yōu)于靜態(tài)代理,靜態(tài)代理效率要高于動態(tài)代理,設(shè)計模式只是方便我們寫好代碼,靜態(tài)和動態(tài),需要讀者自行斟酌使用。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容