設計模式——代理模式(Proxy)
定義
為其他物件提供一種代理,以控制對這個物件的訪問。代理物件在客戶端和目標物件之間起到中介的作用。(結構型) 如果不知道代理模式,可能大家對代理伺服器都不叫熟悉。代替伺服器代替請求者去發一起對另一個伺服器的請求,他相當於請求的中間人。為什麼要通過這個代理呢,那是因為客戶端直接去訪問伺服器會被拒絕(防火牆遮蔽),而代理伺服器則可以直接訪問伺服器。這裡有兩種應用場景,一種是國內的FQ了(靜態代理),另一種是hacker想掩蓋自己的ip時,往往會通過多層代理伺服器進行訪問/或者不停的切換代理(動態代理,《who am i》電影裡面男主就是通過代理去和另外一個haacker通訊,而且所用的代理一直在變防止被追蹤到)
模板
抽象角色(Subject)
通過介面或抽象類宣告真實角色實現的業務方法。
代理角色(RealSubject)
實現抽象角色,是真實角色的代理,通過真實角色的業務邏輯方法來實現抽象方法,並可以附加自己的操作
真實角色(Proxy)
實現抽象角色,定義真實角色所要實現的業務邏輯,供代理角色呼叫
例項
a) 靜態代理
Main中去呼叫ProxyPrinter中的print方法而不需要關心被代理類(Printer),由於程式碼比較簡單,這裡就不具體展開。
b) 動態代理
這裡列舉了一個可以將任何方法的執行放在指定執行緒(提前建立好的UI執行緒和後臺執行緒)的動態代理實現,具體如下:
假如一個有一個寫檔案的操作類如下:
public class FileWriter {
private void writeBytesToFile(String fileName, Byte[] bytes) {
// 將二進位制檔案寫入到 檔案中
}
}
做過前端開發的應該都知道寫檔案是一個耗時操作,不能在主執行緒中執行,那我們現在怎麼辦?
FileWriter fileWriter = new FileWriter(); FileWriter proxyWriter = ObjectThreadProxy.back(fileWriter, FileWriter.class); proxyWriter.writeBytesToFile("TestFile.txt", xxxx);
上述程式碼通過前面講的ObjectThreadProxy工具類就可以將被代理的物件轉換成proxyWriter,接下來呼叫proxyWriter的任何方法都會執行在子執行緒中。這是如何做到的,具體看一下back方法及ThreadInvocationHandler就知道了:
// back 方法中建立代理類
ThreadInvocationHandler handler = new ThreadInvocationHandler(realObj, syncMode);
Object proxyObj = Proxy.newProxyInstance(class.getClassLoader(), new Class[]{class}, handler);
return proxyObj;
// ThreadInvocationHandler 中invoke方法關鍵程式碼如下:
public Object invoke(Object proxy, final Method method, final Object[] args) {
switch(mode) {
case BACK:
// 在子執行緒執行方法
method.invoke(readObject, args);
break;
case MAIN:
// 在主執行緒中執行
break;
}
優點
1.代理模式能將代理物件與真實物件被呼叫的目標物件分離,一定程度上降低了系統的耦合度,擴充套件性好。
2.保護目標物件。
3.增強目標物件。
缺點
- 建立多個類,增加程式碼閱讀複雜性(所有設計模式通病)
- clone方法只是淺拷貝,除五種基礎型別之外型別都只是簡單的指向引用,不會重新建立成員變數,如需實現需要自定義clone方法。
- 通過clone方法不會呼叫類的建構函式,部分場景(在建構函式中做一些初始化操作的)需要做額外的處理
適用場景
1.保護目標物件
2.增強目標物件
與裝飾模式的區別
對物件的作用
裝飾者:動態的新增或組合物件的行為,在不改變介面的前提下,動態擴充套件物件的功能
代理模式:為其他物件提供一種代理以控制對這個物件的訪問,在不改變介面的前提下,控制物件的訪問
如何使用該物件
裝飾者:通常將原始物件作為引數傳遞給Decorator的建構函式。
代理模式:代理類中建立一個真實物件的例項
注: 其實代理模式也可以作為引數傳遞,這裡是網上很多地方的寫法,自己並不贊同。
模式的核心
裝飾者:強調的是增強自身,在被裝飾之後你能夠在被增強的類上使用增強後的功能。增強後你還是你,只不過能力更強了而已
代理模式:強調要讓別人去做一些本身和你業務沒有太多關係的職責(記錄日誌,設定快取,遠端代理負責網路通訊的一些細節),代理模式是為了實現對物件的控制,因為被代理的物件往往難以直接獲得或者其內部不想暴露出來
其它例項:
待補