Java設計模式之代理模式

前言

代理模式也被稱爲委託模式,它是結構型設計模式的一種。在現實生活中咱們用到相似代理模式的場景有不少,好比代理上網、打官司等。設計模式

定義

爲其餘對象提供一種代理以控制對這個對象的訪問。安全

角色

  • Subject:抽象主題類,聲明真實主題與代理的共同接口方法。
  • RealSubject:真實主題類,代理類所表明的真實主題。客戶端經過代理類間接地調用真實主題類的方法。
  • Proxy:代理類,持有對真實主題類的引用,在其所實現的接口方法中調用真實主題類中相應的接口方法執行。
  • client:客戶端類。

類型

從編碼角度分類

  • 靜態代理
  • 動態代理

從適用範圍分類

  • 遠程代理:爲一個對象在不一樣的地址空間提供局部表明,這樣系統能夠將 Server 部分的實現隱藏。
  • 虛擬代理:使用一個代理對象表示一個十分耗資源的對象並在真正須要是才建立。
  • 安全代理:用來控制真實對象訪問的權限。通常用於真實對象有不一樣的訪問權限時。
  • 智能指引:當調用真實的對象時,代理處理另一些事,好比計算機真實對象的引用計數,當該對象沒有引用時,能夠自動釋放它;或者訪問一個實際對象時,檢查是否已經可以鎖定它,以確保其餘對象不能改變它。

靜態代理模式的簡單實現

場景描述

我多年沒有回哈爾濱了,很想念哈爾濱的秋林紅腸味道。可是本人由於工做一直很忙抽不開身,不可以親自回哈爾濱購買,因而就拜託在哈爾濱的朋友幫我購買秋林紅腸。bash

  1. 抽象主題類:抽象主題類具備真實主題類和代理的共同接口方法 buy
public interface IShop {
    void buy();
}
複製代碼
  1. 真實主題類:這個購買者 Giants 就是我,實現了 IShop 接口提供的 buy 方法。
public class Giants implements IShop {
    @Override
    public void buy() {
        System.out.println("購買");
    }
}
複製代碼
  1. 代理類:我找的代理類一樣也要實現 IShop 接口,而且要持有被代理者,在 buy 方法中調用了被代理者的 buy 方法。
public class Purchasing implements IShop {
    private IShop mShop;

    public Purchasing(IShop shop) {
        this.mShop = shop;
    }

    @Override
    public void buy() {
        mShop.buy();
    }
}
複製代碼
  1. 客戶端類:客戶端類的代碼就是包含了真實主題類(被代理者),最終調用的都是真實主題類(被代理者)實現的方法。
public class Client {
    public static void main(String[] args) {
        IShop giants = new Giants();
        IShop purchasing = new Purchasing(giants);
        purchasing.buy();
    }
}
複製代碼

動態代理模式的簡單實現

場景描述

上面的例子是一個靜態的代理,在代碼運行前已經存在了代理類的 class 編譯文件;而動態代理則是在帶來運行時經過反射來動態地生成代理類的對象,並肯定到底代理誰。咱們在編碼階段無需知道代理誰,代理誰將會在代碼運行時覺定。ide

  1. 建立動態代理類
/**
 * 實現Java提供的動態代理接口 InvocationHandler ,實現該接口須要重寫 invoke 方法
 */
public class DynamicPurchasing implements InvocationHandler {
    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("Giants在買買買");
        }
        return result;
    }
}
複製代碼
  1. 修改客戶端類代碼以下:調用 Proxy.newProxyInstance 來生成動態代理類,調用 purchasingbuy 方法會調用 mDynamicPurchasinginvoke 方法。
public class Client {
    public static void main(String[] args) {
        //建立 Giants
        IShop giants = new Giants();
        //建立動態代理
        DynamicPurchasing mDynamicPurchasing = new DynamicPurchasing(giants);
        //建立 giants 的 ClassLoader
        ClassLoader loader = giants.getClass().getClassLoader();
        //動態建立代理類
        IShop purchasing = (IShop) Proxy.newProxyInstance(loader, new Class[] {IShop.class}, mDynamicPurchasing);
        purchasing.buy();
    }
}
複製代碼

優勢

  • 真實主題類就是實現實際的業務邏輯,不用關心其餘非本職工做。
  • 真實主題類隨時都會發生變化;可是由於它實現了公共的接口,因此代理類能夠不作任何修改就可以使用。
相關文章
相關標籤/搜索