Android的設(shè)計模式-代理模式

前言

Android的設(shè)計模式系列文章介紹河哑,歡迎關(guān)注蜂林,持續(xù)更新中:

Android的設(shè)計模式-設(shè)計模式的六大原則
一句話總結(jié)23種設(shè)計模式則
創(chuàng)建型模式:
Android的設(shè)計模式-單例模式
Android的設(shè)計模式-建造者模式
Android的設(shè)計模式-工廠方法模式
Android的設(shè)計模式-簡單工廠模式
Android的設(shè)計模式-抽象工廠模式
Android的設(shè)計模式-原型模式
行為型模式:
Android的設(shè)計模式-策略模式
Android的設(shè)計模式-狀態(tài)模式
Android的設(shè)計模式-責(zé)任鏈模式
Android的設(shè)計模式-觀察者模式
Android的設(shè)計模式-模板方法模式
Android的設(shè)計模式-迭代器模式
Android的設(shè)計模式-備忘錄模式
Android的設(shè)計模式-訪問者模式
Android的設(shè)計模式-中介者模式
Android的設(shè)計模式-解釋器模式
Android的設(shè)計模式-命令模式
結(jié)構(gòu)型模式:
Android的設(shè)計模式-代理模式
Android的設(shè)計模式-組合模式
Android的設(shè)計模式-適配器模式
Android的設(shè)計模式-裝飾者模式
Android的設(shè)計模式-享元模式
Android的設(shè)計模式-外觀模式
Android的設(shè)計模式-橋接模式

1.定義

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

2.介紹

  • 代理模式屬于結(jié)構(gòu)型模式劣挫。
  • 代理模式也叫委托模式橡淑。
  • 生活中哼蛆,比如代購蕊梧、打官司等等,實際上都是一種代理模式腮介。

3.UML類圖

代理模式UML類圖.jpg
角色說明:
  • Subject(抽象主題類):接口或者抽象類肥矢,聲明真實主題與代理的共同接口方法。
  • RealSubject(真實主題類):也叫做被代理類或被委托類,定義了代理所表示的真實對象甘改,負(fù)責(zé)具體業(yè)務(wù)邏輯的執(zhí)行旅东,客戶端可以通過代理類間接的調(diào)用真實主題類的方法。
  • Proxy(代理類):也叫委托類十艾,持有對真實主題類的引用抵代,在其所實現(xiàn)的接口方法中調(diào)用真實主題類中相應(yīng)的接口方法執(zhí)行。
  • Client(客戶端類):使用代理模式的地方忘嫉。

4.實現(xiàn)

以海外代購為例荤牍,在國內(nèi)的人想買國外的東西只能去找國外的人去進行代購。

4.1 創(chuàng)建抽象主題類

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

    public interface People {
        
        void buy();//購買
    }
4.2 創(chuàng)建真實主題類

國內(nèi)的人想購買某些產(chǎn)品庆冕,定義具體的購買過程:

    public class Domestic implements People {

        @Override
        public void buy() {//具體實現(xiàn)
            System.out.println("國內(nèi)要買一個包");
        }
    }
4.3 創(chuàng)建代理類

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

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

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

        @Override
        public void buy() {
            System.out.println("我是海外代購:");
            mPeople.buy();//調(diào)用了被代理者的buy()方法,
        }
    }
4.5 客戶端測試:
     public void test() {
        People domestic = new Domestic();        //創(chuàng)建國內(nèi)購買人
        People oversea = new Oversea(domestic);  //創(chuàng)建海外代購類并將domestic作為構(gòu)造函數(shù)傳遞
        oversea.buy();                           //調(diào)用海外代購的buy()
    }
輸出結(jié)果:
我是海外代購:
國內(nèi)要買一個包

5 靜態(tài)代理與動態(tài)代理

??從代碼的角度來分康吵,代理可以分為兩種:一種是靜態(tài)代理,另一種是動態(tài)代理访递。

??靜態(tài)代理就是在程序運行前就已經(jīng)存在代理類的字節(jié)碼文件晦嵌,代理類和委托類的關(guān)系在運行前就確定了。上面的例子實現(xiàn)就是靜態(tài)代理拷姿。

??動態(tài)代理類的源碼是在程序運行期間根據(jù)反射等機制動態(tài)的生成惭载,所以不存在代理類的字節(jié)碼文件。代理類和委托類的關(guān)系是在程序運行時確定响巢。

??下面我們實現(xiàn)動態(tài)代理描滔,Java提供了動態(tài)的代理接口InvocationHandler,實現(xiàn)該接口需要重寫invoke()方法:

5.1 創(chuàng)建動態(tài)代理類
    public class DynamicProxy implements InvocationHandler {//實現(xiàn)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("海外動態(tài)代理調(diào)用方法: "+method.getName());
            Object result = method.invoke(obj, args);//調(diào)用被代理的對象的方法
            return result;
        }
    }
5.2 修改客戶端的測試方法:
    public void test() {
        People domestic = new Domestic();                                 //創(chuàng)建國內(nèi)購買人
        DynamicProxy proxy = new DynamicProxy(domestic);                  //創(chuàng)建動態(tài)代理
        ClassLoader classLoader = domestic.getClass().getClassLoader();   //獲取ClassLoader
        People oversea = (People) Proxy.newProxyInstance(classLoader, new Class[]{People.class}, proxy); //通過 Proxy 創(chuàng)建海外代購實例 抵乓,實際上通過反射來實現(xiàn)的伴挚。
        oversea.buy();//調(diào)用海外代購的buy()
    }
輸出結(jié)果:
海外動態(tài)代理調(diào)用方法: buy
國內(nèi)要買一個包
5.3 靜態(tài)代理與動態(tài)代理比較

靜態(tài)代理的缺點:

  1. 靜態(tài)代理如果接口新增一個方法,除了所有實現(xiàn)類(真實主題類)需要實現(xiàn)這個方法外灾炭,所有代理類也需要實現(xiàn)此方法茎芋。增加了代碼維護的復(fù)雜度。
  2. 代理對象只服務(wù)于一種類型的對象蜈出,如果要服務(wù)多類型的對象田弥。必須要為每一種對象都進行代理,靜態(tài)代理在程序規(guī)模稍大時就無法勝任了铡原。

動態(tài)代理的優(yōu)點:

  1. 可以通過一個代理類完成全部的代理功能偷厦,接口中聲明的所有方法都被轉(zhuǎn)移到調(diào)用處理器一個集中的方法中處理(InvocationHandler.invoke)。當(dāng)接口方法數(shù)量較多時燕刻,我們可以進行靈活處理只泼,而不需要像靜態(tài)代理那樣每一個方法進行中轉(zhuǎn)。
  2. 動態(tài)代理的應(yīng)用使我們的類職責(zé)更加單一卵洗,復(fù)用性更強请唱。

動態(tài)代理的缺點:

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

6. 應(yīng)用場景

  • 當(dāng)一個對象不能或者不想直接訪問另一個對象時,可以通過一個代理對象來間接訪問本橙。為保證客戶端使用的透明性扳躬,委托對象和代理對象要實現(xiàn)同樣的接口。

  • 被訪問的對象不想暴露全部內(nèi)容時甚亭,可以通過代理去掉不想被訪問的內(nèi)容贷币。

  • 根據(jù)適用范圍,代理模式可以分為以下幾種:

    • 遠(yuǎn)程代理:為一個對象在不同的地址空間提供局部代表狂鞋,這樣系統(tǒng)可以將Server部分的事項隱藏片择。
    • 虛擬代理:如果要創(chuàng)建一個資源消耗較大的對象,可以先用一個代理對象表示骚揍,在真正需要的時候才真正創(chuàng)建。
    • 保護代理:用代理對象控制對一個對象的訪問啰挪,給不同的用戶提供不同的訪問權(quán)限信不。
    • 智能引用:在引用原始對象的時候附加額外操作,并對指向原始對象的引用增加引用計數(shù)亡呵。

7. 優(yōu)點

  • 代理作為調(diào)用者和真實主題的中間層,降低了模塊間和系統(tǒng)的耦合性抽活。
  • 可以以一個小對象代理一個大對象,達到優(yōu)化系統(tǒng)提高運行速度的目的。
  • 代理對象能夠控制調(diào)用者的訪問權(quán)限锰什,起到了保護真實主題的作用下硕。

8. 缺點

  • 由于在調(diào)用者和真實主題之間增加了代理對象,因此可能會造成請求的處理速度變慢汁胆。
  • 實現(xiàn)代理模式需要額外的工作(有些代理模式的實現(xiàn)非常復(fù)雜)梭姓,從而增加了系統(tǒng)實現(xiàn)的復(fù)雜度。

9. Android中的源碼分析

Android的源碼中多個地方都用到代理模式嫩码,比如ActivityManagerProxy這個代理類誉尖。鑒于ActivityManager的代碼非常復(fù)雜,這里就不進行分析了铸题,后面會另開文章進行具體分析铡恕,這里主要對ActivityManager中的代理模式進行簡單的分析一下。先看下相關(guān)類的結(jié)構(gòu)圖:

ActivityManager相關(guān)類的結(jié)構(gòu)圖.png

??由上圖可以看到:ActivityManagerProxyActivityManagerNative都是實現(xiàn)IActivityManager這個接口丢间,IActivityManager就是抽象主題了探熔,ActivityManagerProxy一看就是代理類,而真實主題則是ActivityManagerNative烘挫,實際上ActivityManagerNative是個抽象類诀艰,真正的具體實現(xiàn)是在它的子類ActivityManagerService中。

??這里的代理實質(zhì)是個遠(yuǎn)程代理,ActivityManagerProxyActivityManagerService是運行在不同的進程空間中的涡驮。

??關(guān)于代理模式的分析就到這里為止了暗甥,其他的東西就不分析了。

相關(guān)文章閱讀
Android的設(shè)計模式-設(shè)計模式的六大原則
一句話總結(jié)23種設(shè)計模式則
創(chuàng)建型模式:
Android的設(shè)計模式-單例模式
Android的設(shè)計模式-建造者模式
Android的設(shè)計模式-工廠方法模式
Android的設(shè)計模式-簡單工廠模式
Android的設(shè)計模式-抽象工廠模式
Android的設(shè)計模式-原型模式
行為型模式:
Android的設(shè)計模式-策略模式
Android的設(shè)計模式-狀態(tài)模式
Android的設(shè)計模式-責(zé)任鏈模式
Android的設(shè)計模式-觀察者模式
Android的設(shè)計模式-模板方法模式
Android的設(shè)計模式-迭代器模式
Android的設(shè)計模式-備忘錄模式
Android的設(shè)計模式-訪問者模式
Android的設(shè)計模式-中介者模式
Android的設(shè)計模式-解釋器模式
Android的設(shè)計模式-命令模式
結(jié)構(gòu)型模式:
Android的設(shè)計模式-代理模式
Android的設(shè)計模式-組合模式
Android的設(shè)計模式-適配器模式
Android的設(shè)計模式-裝飾者模式
Android的設(shè)計模式-享元模式
Android的設(shè)計模式-外觀模式
Android的設(shè)計模式-橋接模式

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末捉捅,一起剝皮案震驚了整個濱河市撤防,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌棒口,老刑警劉巖寄月,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異无牵,居然都是意外死亡漾肮,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進店門茎毁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來克懊,“玉大人,你說我怎么就攤上這事七蜘√犯龋” “怎么了?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵橡卤,是天一觀的道長扮念。 經(jīng)常有香客問我,道長碧库,這世上最難降的妖魔是什么柜与? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮嵌灰,結(jié)果婚禮上弄匕,老公的妹妹穿的比我還像新娘。我一直安慰自己伞鲫,他們只是感情好粘茄,可當(dāng)我...
    茶點故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著秕脓,像睡著了一般柒瓣。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上吠架,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天芙贫,我揣著相機與錄音胆描,去河邊找鬼仆嗦。 笑死,一個胖子當(dāng)著我的面吹牛沃但,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拣挪,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼擦酌,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了菠劝?” 一聲冷哼從身側(cè)響起赊舶,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎赶诊,沒想到半個月后笼平,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡舔痪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年寓调,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锄码。...
    茶點故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡夺英,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出巍耗,到底是詐尸還是另有隱情秋麸,我是刑警寧澤,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布炬太,位于F島的核電站,受9級特大地震影響驯耻,放射性物質(zhì)發(fā)生泄漏亲族。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一可缚、第九天 我趴在偏房一處隱蔽的房頂上張望霎迫。 院中可真熱鬧,春花似錦帘靡、人聲如沸知给。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽涩赢。三九已至,卻和暖如春轩勘,著一層夾襖步出監(jiān)牢的瞬間筒扒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工绊寻, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留花墩,地道東北人悬秉。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像冰蘑,于是被迫代替她去往敵國和親和泌。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,500評論 2 359