代理模式總結

LiuJian-Android發表於2018-03-05

1 簡介

代理模式也被陳各位委託模式,它是結構型設計模式的一種。在現實生活中我們用到類似代理模式的場景有很多,比如代理上網、打官司等。
定義:為其他物件提供一種代理以控制對這個物件的訪問。
代理模式的結構如下圖所示:

代理模式總結
在代理模式中有如下角色:

  • Subject:抽象主題類,宣告真實主題與代理的共同介面方法
  • RealSubject:真實主題類,代理類所代表的真實主題。客戶端通過代理類間接的呼叫真實主題類的方法
  • Proxy:代理類,持有對真實主題類的引用,在其所實現的介面方法中呼叫真實主題類中的相應的介面方法執行
  • Client:客戶端類

2 代理模式的簡單實現

我要購買哈爾濱紅腸,但是不能親自去,於是就託在哈爾濱的朋友幫我購買。

2.1 抽象主題類

抽象主題類具有真實主題類和代理的共同介面方法,共同的方法就是購買:

public interface IShop{
    void buy();
}
複製程式碼

2.2 真實主題類

這個購買者,也就是我,實現了IShop介面提供的buy()方法,如下所示:

public class Person implements IShop{
    @Override
    public void buy(){
        System.out.println("購買");
    }
}
複製程式碼

2.3 代理類

我找的代理類同樣也要實現IShop介面,並且要持有被代理者,在buy()方法中呼叫了被代理者的buy()方法:

public class Purchasing implements IShop{
    private IShop mShop;
    public Purchasing(IShop shop){
        mShop = shop;
    }
    
    @Override
    public void buy(){
        mShop.buy();
    }
}
複製程式碼

2.4 客戶端類

public class Client{
    public static void main(String[] args){
        IShop person = new Person();
        IShop purchasing = new Purchasing(person);
        purchasing.buy();
    }
}
複製程式碼

客戶端類的程式碼就是代理類包含了真實主題類(被代理者),最終呼叫的都是真實主題類(被代理者)實現的方法。在上面的例子中就是Person類的buy方法,所以執行的結果就是“購買”。

3 動態代理的實現

從編碼的角度來說,代理模式分為靜態代理和動態代理。上面的例子就是靜態代理,在程式碼執行前就已經存在了代理類的class編譯檔案;而動態代理則是在程式碼執行時通過反射來動態的生成代理類的物件,並確定到底來代理誰。也就是我們在編碼階段無需知道代理誰,代理誰將會在程式碼執行時決定。Java提供了動態的代理介面InvocationHandler,實現該介面需要重寫invoke()方法。下面我們在上面靜態代理的例子上做修改。首先建立動態代理類,程式碼如下所示:

public void DynammicPurchasing implements InvocationHander{
    private Object obj;
    public DynamicPurchasing(Object obj){
        this.obj = obj;
    }
    
    @Override
    public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{
        Object result = method.invoke(obj,args);
        if(method.getName().equals("buy")){
            System.out.println("買買買");
        }
        return result;
    }
}
複製程式碼

在動態代理中我們宣告一個Object的引用,該引用指向被代理類,我們呼叫被代理類的具體方法在invoke方法中執行。接下來我們修改客戶端程式碼:

public class Client{
    public static void main(String[] args){
        //建立Person
        IShop person = new Person();
        //建立動態代理
        DynamicPurchasing mDynamicPurchasing = new DynamicPurchasing(person);
        //建立person的ClassLoader
        ClassLoader loader = person.getClass().getClassLoader();
        //動態建立代理
        IShop purchasing = (IShop)Proxy.newProxyIntance(loader,new Class[]{IShop.class},mDynamicPurchasing);
        purchasing.buy();
    }
}
複製程式碼

4代理模式的型別和優點

4.1 編碼分類

  • 靜態代理:在程式碼執行前就已經存在了代理類的class編譯檔案
  • 動態代理:在程式碼執行時通過反射來動態的生成代理類的物件,並確定到底來代理誰

4.2 適用範圍分類

  • 遠端代理:為一個物件在不同的地址空間提供區域性代表,這樣系統就可以將Server部分的實現隱藏
  • 虛擬代理:使用一個代理物件表示一個十分耗費資源的物件並在真正需要時才建立
  • 安全代理:用來控制真實物件訪問時的許可權。一般用於真實物件有不同的訪問許可權時
  • 智慧指引:當呼叫真實的物件時,代理處理另外一些事,比如計算真實物件的引用計數,當該物件沒有引用時,可以自動釋放它;或者訪問一個十幾物件時檢查是否已經能夠鎖定他,確保其不能改變他

4.3 優點

  • 真實主題類就是實現實際的業務邏輯,不用關係你其他非本職的工作
  • 真實主題類隨時都會發生變化;但是因為他實現了公共的介面,所以代理類可以不做任何修改就能夠使用

參考《Android進階之光》 作者:劉望舒

相關文章