代理模式
定義:為一個對象提供一個替身或占位符以控制對這個對象的訪問。被代理的對象可以是遠程的對象、創建開銷大的對象、需要安全控制的對象。
角色: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方法 調用后