設計模式——代理模式(Proxy)

定義

爲其他對象提供一種代理,以控制對這個對象的訪問。代理對象在客戶端和目標對象之間起到中介的作用。(結構型)

如果不知道代理模式,可能大家對代理服務器都不叫熟悉。代替服務器代替請求者去發一起對另一個服務器的請求,他相當於請求的中間人。爲什麼要通過這個代理呢,那是因爲客戶端直接去訪問服務器會被拒絕(防火牆屏蔽),而代理服務器則可以直接訪問服務器。這裏有兩種應用場景,一種是國內的翻牆了(靜態代理),另一種是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.增強目標對象。

缺點

  1. 創建多個類,增加代碼閱讀複雜性(所有設計模式通病)
  2. clone方法只是淺拷貝,除五種基礎類型之外類型都只是簡單的指向引用,不會重新創建成員變量,如需實現需要自定義clone方法。
  3. 通過clone方法不會調用類的構造函數,部分場景(在構造函數中做一些初始化操作的)需要做額外的處理

適用場景

1.保護目標對象
2.增強目標對象

與裝飾模式的區別

對對象的作用
裝飾者:動態的新增或組合對象的行爲,在不改變接口的前提下,動態擴展對象的功能
代理模式:爲其他對象提供一種代理以控制對這個對象的訪問,在不改變接口的前提下,控制對象的訪問

如何使用該對象
裝飾者:通常將原始對象作爲參數傳遞給Decorator的構造函數。
代理模式:代理類中創建一個真實對象的實例
注: 其實代理模式也可以作爲參數傳遞,這裏是網上很多地方的寫法,自己並不贊同。

模式的核心
裝飾者:強調的是增強自身,在被裝飾之後你能夠在被增強的類上使用增強後的功能。增強後你還是你,只不過能力更強了而已
代理模式:強調要讓別人去做一些本身和你業務沒有太多關係的職責(記錄日誌,設置緩存,遠程代理負責網絡通信的一些細節),代理模式是爲了實現對對象的控制,因爲被代理的對象往往難以直接獲得或者其內部不想暴露出來

其它實例:

待補充

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章