Android常見設計模式七:代理模式

對于開發人員來說,設計模式有時候就是一道坎,但是設計模式又非常有用,過了這道坎,它可以讓你水平提高一個檔次。而在android開發中,必要的了解一些設計模式又是必須的,因為設計模式在Android源碼中,可以說是無處不在。對于想系統的學習設計模式的同學,這里推薦一本書,《大話設計模式》。


Android常用設計模式系列:

面向對象的基礎特征
面向對象的設計原則
單例模式
模板模式
適配器模式
工廠模式
代理模式
原型模式
策略模式
Build模式
觀察者模式
裝飾者模式
中介模式
門面模式


代理模式

代理模式是非常常見的設計模式之一,寫個筆記,記錄一下我的學習過程和心得。

首先了解一些代理模式的定義。

為其他對象提供一種代理以控制這個對象的訪問。

涉及角色及說明:

Subject(抽象主題類):接口或者抽象類,聲明真實主題與代理的共同接口方法。
RealSubject(真實主題類):也叫做被代理類或被委托類,定義了代理所表示的真實對象,負責具體業務邏輯的執行,客戶端可以通過代理類間接的調用真實主題類的方法。
Proxy(代理類):也叫委托類,持有對真實主題類的引用,在其所實現的接口方法中調用真實主題類中相應的接口方法執行。
Client(客戶端類):使用代理模式的地方。

理解:

  • 代理模式屬于結構型模式。
  • 代理模式也叫委托模式。
  • 生活中,比如代購、打官司等等,實際上都是一種代理模式。

以海外代購為例,在國內的人想買國外的東西只能去找國外的人去進行代購。

1 創建抽象主題類

人都是有購買這個方法的:

    public interface People {
        void buy();//購買
    }

2 創建真實主題類

國內的人想購買某些產品,定義具體的購買過程:

    public class Domestic implements People {

        @Override
        public void buy() {//具體實現
            System.out.println("國內要買一個包");
        }
    }

3 創建代理類

海外的代購黨需要知道是誰(持有真實主題類的引用)想購買啥產品:

     public class Oversea implements People {
        People mPeople;//持有People類的引用

        public Oversea(People people) {
            mPeople = people;
        }

        @Override
        public void buy() {
            System.out.println("我是海外代購:");
            mPeople.buy();//調用了被代理者的buy()方法,
        }
    }

5 客戶端測試:

     public void test() {
        People domestic = new Domestic();        //創建國內購買人
        People oversea = new Oversea(domestic);  //創建海外代購類并將domestic作為構造函數傳遞
        oversea.buy();                           //調用海外代購的buy()
    }

輸出結果:

我是海外代購:
國內要買一個包

靜態代理與動態代理

從代碼的角度來分,代理可以分為兩種:一種是靜態代理,另一種是動態代理。

  • 靜態代理就是在程序運行前就已經存在代理類的字節碼文件,代理類和委托類的關系在運行前就確定了。上面的例子實現就是靜態代理。
  • 動態代理類的源碼是在程序運行期間根據反射等機制動態的生成,所以不存在代理類的字節碼文件。代理類和委托類的關系是在程序運行時確定。
    ??下面我們實現動態代理,Java提供了動態的代理接口InvocationHandler,實現該接口需要重寫invoke()方法:
1 創建動態代理類
    public class DynamicProxy implements InvocationHandler {//實現InvocationHandler接口
        private Object obj;//被代理的對象

        public DynamicProxy(Object obj) {
            this.obj = obj;
        }

        //重寫invoke()方法
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            System.out.println("海外動態代理調用方法: "+method.getName());
            Object result = method.invoke(obj, args);//調用被代理的對象的方法
            return result;
        }
    }
2 修改客戶端的測試方法:
    public void test() {
        People domestic = new Domestic();                                 //創建國內購買人
        DynamicProxy proxy = new DynamicProxy(domestic);                  //創建動態代理
        ClassLoader classLoader = domestic.getClass().getClassLoader();   //獲取ClassLoader
        People oversea = (People) Proxy.newProxyInstance(classLoader, new Class[]{People.class}, proxy); //通過 Proxy 創建海外代購實例 ,實際上通過反射來實現的。
        oversea.buy();//調用海外代購的buy()
    }

輸出結果:

海外動態代理調用方法: buy
國內要買一個包

靜態代理與動態代理比較

靜態代理的缺點:

靜態代理如果接口新增一個方法,除了所有實現類(真實主題類)需要實現這個方法外,所有代理類也需要實現此方法。增加了代碼維護的復雜度。
代理對象只服務于一種類型的對象,如果要服務多類型的對象。必須要為每一種對象都進行代理,靜態代理在程序規模稍大時就無法勝任了。

動態代理的優點:

可以通過一個代理類完成全部的代理功能,接口中聲明的所有方法都被轉移到調用處理器一個集中的方法中處理(InvocationHandler.invoke)。當接口方法數量較多時,我們可以進行靈活處理,而不需要像靜態代理那樣每一個方法進行中轉。
動態代理的應用使我們的類職責更加單一,復用性更強。

動態代理的缺點:

不能對類進行代理,只能對接口進行代理,如果我們的類沒有實現任何接口,那么就不能使用這種方式進行動態代理(因為$Proxy()這個類集成了Proxy,Java的集成不允許出現多個父類)。

廣泛應用

總結

總結一下代理模式的優缺點

優點

代理作為調用者和真實主題的中間層,降低了模塊間和系統的耦合性。
可以以一個小對象代理一個大對象,達到優化系統提高運行速度的目的。
代理對象能夠控制調用者的訪問權限,起到了保護真實主題的作用。

缺點

由于在調用者和真實主題之間增加了代理對象,因此可能會造成請求的處理速度變慢。
實現代理模式需要額外的工作(有些代理模式的實現非常復雜),從而增加了系統實現的復雜度。

適用場景

當一個對象不能或者不想直接訪問另一個對象時,可以通過一個代理對象來間接訪問。為保證客戶端使用的透明性,委托對象和代理對象要實現同樣的接口。
被訪問的對象不想暴露全部內容時,可以通過代理去掉不想被訪問的內容。

根據適用范圍,代理模式可以分為以下幾種:

  • 遠程代理:為一個對象在不同的地址空間提供局部代表,這樣系統可以將Server部分的事項隱藏。
  • 虛擬代理:如果要創建一個資源消耗較大的對象,可以先用一個代理對象表示,在真正需要的時候才真正創建。
  • 保護代理:用代理對象控制對一個對象的訪問,給不同的用戶提供不同的訪問權限。
  • 智能引用:在引用原始對象的時候附加額外操作,并對指向原始對象的引用增加引用計數。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,182評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,489評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,290評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,776評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,510評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,866評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,860評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,036評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,585評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,331評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,536評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,058評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,754評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,154評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,469評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,273評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,505評論 2 379

推薦閱讀更多精彩內容