代理模式

代理模式
定義:為一個對象提供一個替身或占位符以控制對這個對象的訪問。被代理的對象可以是遠程的對象、創建開銷大的對象、需要安全控制的對象。
角色:subject:真正對象與代理對象都要實現的接口,允許客戶可以像處理真正對象一樣處理代理對象
proxy:代理對象,并持有真正對象的引用,必要時可以將請求轉發給真正對象。
realSubject:真正對象,代理對象控制對其訪問

類型:遠程代理:管理客戶端與遠程之間的交互
虛擬代理:創建開銷大的對象的代表。虛擬代理經常知道我們真正需要一個對象的時候才創建它,當對象在創建前和創建中時,由虛擬代理來扮演對象的替身。對象創建后,代理就會將請求直接委托給對象。
動態代理:
保護代理:基于調用者控制對對象方法的訪問
防火墻代理(Firewall Proxy):控制網絡資源訪問,保護主題免于“壞客戶”的侵害
智能引用代理(Smart Reference Proxy):主題被訪問時,進行額外的動作
緩存代理(Caching Proxy):為開銷大的運算結果提供暫時的存儲,也允許多個客戶共享結果,以減少計算或網絡延遲。(web服務器代理,內容管理,出版系統)
同步代理(Synchronization Proxy)多線程的情況下為主題提供安全的訪問。(javaSpaces為分散式環境內的潛在對象集合提供同步訪問控制)
復雜隱藏代理(Complexity Hiding Proxy):用來隱藏一個類得復雜集合的復雜度,并進行控制訪問,也稱為外觀代理(Facade Proxy)
寫入時復制代理(Copy-On-Write Proxy):用來控制對象的復制,方法是延遲對象的復制,知道客戶真的需要為止。是虛擬代理的變體。(java5,CopyOnWriteArrayList)

代理模式與裝飾者(Decorator)模式區別:兩者類圖一樣,但是目的不同,裝飾者是為給對象增加行為,而代理模式是控制對對象的訪問。
代理模式有時候會創建真實對象,裝飾者模式不會創建被裝飾的對象
代理不會講一個主題包裝多次,裝飾者不做限制

使用方式
一般使用工廠模式,實例化并返回代理對象

/**
 * 代理與真正對象的共同接口
 *
 */
public interface Subject {

    public void doSomething();
}

/**
 * 真正對象
 *
 */
public class RealSubject implements Subject {

    @Override
    public void doSomething() {
        System.out.println("真正對象的操作");
    }

}

/**
 * 代理類
 *
 */
public class ProxySubject implements Subject {
    
    private RealSubject subject;
    
    public ProxySubject(){
        subject = new RealSubject();
    }

    @Override
    public void doSomething() {
        System.out.println("代理對象添加功能");
        subject.doSomething();
        System.out.println("代理對象添加功能");
    }

}

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

    public static void main(String[] args) {
        ProxySubject subject = new ProxySubject();
        subject.doSomething();
    }

}

輸出:
    代理對象添加功能
    真正對象的操作
    代理對象添加功能

動態代理 JDK 5引入的動態代理機制,允許開發人員在運行時刻動態的創建出代理類及其對象。在運行時刻,可以動態創建出一個實現了多個接口的代理類。每個代理類的對象都會關聯一個表示內部處理邏輯的InvocationHandler接 口的實現。當使用者調用了代理對象所代理的接口中的方法的時候,這個調用的信息會被傳遞給InvocationHandler的invoke方法。在 invoke方法的參數中可以獲取到代理對象、方法對應的Method對象和調用的實際參數。invoke方法的返回值被返回給使用者。這種做法實際上相 當于對方法調用進行了攔截。
動態代理主要使用java.lang.reflect包下的InvocationHandler接口、Proxy類。InvocationHandler用來實現代理行為,Proxy用來創建代理類

 /**
 * 切面接口
 *
 */
public interface AopInterface {

    public void addBefore(String str);
    
    public void addEnd(String str);
}

public class Aop implements AopInterface {

    @Override
    public void addBefore(String str) {
        System.out.println(str+" 調用前");
    }

    @Override
    public void addEnd(String str) {
        System.out.println(str+" 調用后");
    }

}

/**
 * 代理行為
 *
 */
public class AopInvocationHandler implements InvocationHandler {
    
    private AopInterface aop;
    private Object realObject;
    
    public AopInvocationHandler(Object object){
        aop = new Aop();
        realObject = object;
    }

    @Override
    public Object invoke(Object object, Method method, Object[] arg2)
            throws Throwable {
//      method.invoke(object, arg2); 使用object會照成死循環,不清楚有什么用
        aop.addBefore(realObject.getClass().getName()+"類的"+method.getName()+"方法");
        Object obj = method.invoke(realObject, arg2);
        aop.addEnd(realObject.getClass().getName()+"類的"+method.getName()+"方法");
        return obj;
    }

}

/**
 * 代理與真正對象的共同接口
 *
 */
public interface Subject {

    public void doSomething();
}

/**
 * 真正對象
 *
 */
public class RealSubject implements Subject {

    @Override
    public void doSomething() {
        System.out.println("真正對象的操作");
    }

}

/**
 * 測試類
 *
 */
public class Test {
    
    public static void main(String[] args) {
        Subject subject = new RealSubject();
        Subject proxy = (Subject)Proxy.newProxyInstance(subject.getClass().getClassLoader(), 
                subject.getClass().getInterfaces(), new AopInvocationHandler(subject));
        proxy.doSomething();
    }

}

輸出:
    proxy.dynamic.RealSubject類的doSomething方法 調用前
    真正對象的操作
    proxy.dynamic.RealSubject類的doSomething方法 調用后

來源:http://blog.csdn.net/lansuiyun/article/details/11992373

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容