定義
為其他對象提供一種代理,以控制對這個對象的訪問。代理對象在客戶端和目標對象之間起到中介的作用。(結構型)
如果不知道代理模式,可能大家對代理服務器都不叫熟悉。代替服務器代替請求者去發一起對另一個服務器的請求,他相當於請求的中間人。為什么要通過這個代理呢,那是因為客戶端直接去訪問服務器會被拒絕(防火牆屏蔽),而代理服務器則可以直接訪問服務器。這里有兩種應用場景,一種是國內的翻牆了(靜態代理),另一種是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的構造函數。
代理模式:代理類中創建一個真實對象的實例
注: 其實代理模式也可以作為參數傳遞,這里是網上很多地方的寫法,自己並不贊同。
模式的核心
裝飾者:強調的是增強自身,在被裝飾之后你能夠在被增強的類上使用增強后的功能。增強后你還是你,只不過能力更強了而已
代理模式:強調要讓別人去做一些本身和你業務沒有太多關系的職責(記錄日志,設置緩存,遠程代理負責網絡通信的一些細節),代理模式是為了實現對對象的控制,因為被代理的對象往往難以直接獲得或者其內部不想暴露出來
其它實例:
待補充