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

代理模式也叫委托模式调缨,是結(jié)構(gòu)型設(shè)計模式疮鲫。代理就是讓別人幫你做事,比如幫你帶飯弦叶,請律師打官司什么的俊犯。

博客地址

定義

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

使用場景

  • 當(dāng)一個對象不能或者不想直接訪問另一個對象時湾蔓,可以通過一個代理對象來間接訪問瘫析。為保證客戶端使用的透明性,委托對象和代理對象要實現(xiàn)同樣的接口默责。
  • 被訪問的對象不想暴露全部內(nèi)容時贬循,可以通過代理去掉不想被訪問的內(nèi)容。

UML

  • Subject: 抽象主題類桃序,聲明真是主體與代理主題的共同接口方法杖虾。
  • RealSubject: 真實主題類,定義了代理所表示的真是對象媒熊,執(zhí)行具體的業(yè)務(wù)方法奇适。客戶端通過代理類來間接的調(diào)動這個真實主題中的方法芦鳍。
  • ProxySubject: 代理類嚷往,持有一個真實類的引用,在接口方法中調(diào)用真實主題相應(yīng)的方法柠衅,達(dá)到代理的作用皮仁。

簡單實現(xiàn)

就以打官司為例。我們一般人要打官司都要找個律師來代理菲宴。

靜態(tài)代理

先建立一個起訴類的接口:

public interface ILawsuit {
    void submit();//提交申請
    void burden();//進(jìn)行舉證
    void defend();//開始辯護(hù)
    void finish();//訴訟完成
}

真正的起訴者:

public class Civilian implements ILawsuit {
    @Override
    public void submit() {
        System.out.println("起訴");
    }

    @Override
    public void burden() {
        System.out.println("舉證");
    }

    @Override
    public void defend() {
        System.out.println("辯護(hù)");
    }

    @Override
    public void finish() {
        System.out.println("勝訴");
    }
}

找的律師:

public class Lawyer implements ILawsuit {
    private ILawsuit civilian;

    public Lawyer(ILawsuit civilian) {
        this.civilian = civilian;
    }

    @Override
    public void submit() {
        civilian.submit();
    }

    @Override
    public void burden() {
        civilian.burden();
    }

    @Override
    public void defend() {
        civilian.defend();
    }

    @Override
    public void finish() {
        civilian.finish();
    }
}

客戶端調(diào)用贷祈,調(diào)用律師的方法,通過律師調(diào)用真正的su起訴者的方法喝峦。

public class Client {
    public static void main(String[] args) {
        ILawsuit civilian = new Civilian();
        ILawsuit lawyer = new Lawyer(civilian);
        lawyer.submit();
        lawyer.burden();
        lawyer.defend();
        lawyer.finish();
    }
}

輸出:


一個代理可以代理多個類势誊,就像這個律師可以給很多人打官司,只需要在實現(xiàn)一個具體的ILawsuit就行了谣蠢。代理會根據(jù)傳進(jìn)來的被代理者調(diào)用傳進(jìn)來的被代理者的方法粟耻。

動態(tài)代理

代理模式大致分為兩大部分:靜態(tài)代理和動態(tài)代理。

上面是是一種靜態(tài)代理眉踱,代理者的代碼時先生成寫好勋颖,然后再對其進(jìn)行編譯,在代碼運行前勋锤,代理類的class編譯文件就已經(jīng)存在了饭玲。

動態(tài)代理是相反的,通過反射動態(tài)的生成代理者對象叁执,也就是說在寫代碼的時候根本不知道要代理誰茄厘,具體代理誰會在執(zhí)行階段決定矮冬。

Java提供了一個便捷的動態(tài)代理接口InvocationHandler,動態(tài)代理類只要實現(xiàn)這個接口就行:

public class DynamicProxy implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return null;
    }
}

看一下動態(tài)代理的用法:

public class DynamicProxy implements InvocationHandler {
    private Object object;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //當(dāng)然這里可以對方法名進(jìn)行判斷過濾 if(method.getName().equals("***"))
        Object result = method.invoke(object,args);
        return result;
    }
}

客戶端調(diào)用:

public class Main {
    public static void main(String[] args) {
        ILawsuit lawsuit = new Civilian();
        DynamicProxy proxy = new DynamicProxy(lawsuit);
        ClassLoader loader = lawsuit.getClass().getClassLoader();
        //動態(tài)創(chuàng)建代理類次哈,需要傳入一個類加載器ClassLoader胎署;一個你希望這個代理實現(xiàn)的接口列表,這里要代理ILawsuit接口窑滞;
        //和一個InvocationHandler的實現(xiàn)琼牧,也就是前面創(chuàng)建的proxy。
        ILawsuit lawyer = (ILawsuit) Proxy.newProxyInstance(loader,new Class[]{ILawsuit.class},proxy);
        lawyer.submit();
        lawyer.burden();
        lawyer.defend();
        lawyer.finish();
    }
}

輸出和上面一毛一樣:

動態(tài)代理并不局限與代理一個接口的實現(xiàn)哀卫,可以根據(jù)運行時傳入的接口巨坊,動態(tài)的生成代理類,然后通過Method的invoke方法來執(zhí)行被代理類的真實方法此改。非常靈活趾撵。

其他分類

靜態(tài)代理和動態(tài)代理是從code方便進(jìn)行分類的。這兩個分類根據(jù)適用范圍來分都可以分為下面幾種:

  • 遠(yuǎn)程代理:為摸個對象在不同的內(nèi)存地址空間提供局部代理共啃,是系統(tǒng)Server部分隱藏占调,以便Client不用考慮Server的存在。
  • 虛擬代理:如果要創(chuàng)建一個資源消耗較大的對象移剪,可以先用一個代理對象表示究珊,在真正需要的時候才真正創(chuàng)建。
  • 保護(hù)代理:用代理對象控制對一個對象的訪問纵苛,給不同的用戶提供不同的訪問權(quán)限剿涮。
  • 智能引用:在引用原始對象的時候附加額外操作,并對指向原始對象的引用增加引用計數(shù)赶站。

總結(jié)

代理模式使用非常廣泛,從分類就能感覺出來纺念,而且其他的設(shè)計模式中也會有代理模式的影子贝椿。

優(yōu)點

優(yōu)點可以從他的適用范圍看出來

  • 協(xié)調(diào)調(diào)用者和被調(diào)用者,降低系統(tǒng)耦合度陷谱。
  • 用小對象代表大對象烙博,減少系統(tǒng)資源消耗,提高系統(tǒng)運行速度烟逊,如虛擬代理渣窜。
  • 控制用戶對唄調(diào)用者的使用權(quán)限,如保護(hù)代理宪躯。

缺點

  • 首先當(dāng)然是比直接調(diào)用原始對象多了一個中間者乔宿,會讓結(jié)構(gòu)有點復(fù)雜。
  • 調(diào)用原始對象的方法要通過代理來調(diào)用访雪,可能會造成請求處理速度變慢详瑞。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末掂林,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子坝橡,更是在濱河造成了極大的恐慌泻帮,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,324評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件计寇,死亡現(xiàn)場離奇詭異锣杂,居然都是意外死亡,警方通過查閱死者的電腦和手機番宁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評論 3 392
  • 文/潘曉璐 我一進(jìn)店門元莫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人贝淤,你說我怎么就攤上這事柒竞。” “怎么了播聪?”我有些...
    開封第一講書人閱讀 162,328評論 0 353
  • 文/不壞的土叔 我叫張陵朽基,是天一觀的道長。 經(jīng)常有香客問我离陶,道長稼虎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,147評論 1 292
  • 正文 為了忘掉前任招刨,我火速辦了婚禮霎俩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘沉眶。我一直安慰自己打却,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,160評論 6 388
  • 文/花漫 我一把揭開白布谎倔。 她就那樣靜靜地躺著柳击,像睡著了一般。 火紅的嫁衣襯著肌膚如雪片习。 梳的紋絲不亂的頭發(fā)上捌肴,一...
    開封第一講書人閱讀 51,115評論 1 296
  • 那天,我揣著相機與錄音藕咏,去河邊找鬼状知。 笑死,一個胖子當(dāng)著我的面吹牛孽查,可吹牛的內(nèi)容都是我干的饥悴。 我是一名探鬼主播,決...
    沈念sama閱讀 40,025評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼铺坞!你這毒婦竟也來了起宽?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,867評論 0 274
  • 序言:老撾萬榮一對情侶失蹤济榨,失蹤者是張志新(化名)和其女友劉穎坯沪,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體擒滑,經(jīng)...
    沈念sama閱讀 45,307評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡况鸣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,528評論 2 332
  • 正文 我和宋清朗相戀三年贡珊,在試婚紗的時候發(fā)現(xiàn)自己被綠了隧魄。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片茫孔。...
    茶點故事閱讀 39,688評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖库车,靈堂內(nèi)的尸體忽然破棺而出巨柒,到底是詐尸還是另有隱情,我是刑警寧澤柠衍,帶...
    沈念sama閱讀 35,409評論 5 343
  • 正文 年R本政府宣布洋满,位于F島的核電站,受9級特大地震影響珍坊,放射性物質(zhì)發(fā)生泄漏牺勾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,001評論 3 325
  • 文/蒙蒙 一阵漏、第九天 我趴在偏房一處隱蔽的房頂上張望驻民。 院中可真熱鬧,春花似錦履怯、人聲如沸回还。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽柠硕。三九已至,卻和暖如春疹味,著一層夾襖步出監(jiān)牢的瞬間仅叫,已是汗流浹背帜篇。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評論 1 268
  • 我被黑心中介騙來泰國打工糙捺, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人笙隙。 一個月前我還...
    沈念sama閱讀 47,685評論 2 368
  • 正文 我出身青樓洪灯,卻偏偏與公主長得像,于是被迫代替她去往敵國和親竟痰。 傳聞我的和親對象是個殘疾皇子签钩,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,573評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 一掏呼、設(shè)計模式的分類 總體來說設(shè)計模式分為三大類: 創(chuàng)建型模式,共五種:工廠方法模式铅檩、抽象工廠模式憎夷、單例模式、建造者...
    RamboLI閱讀 749評論 0 1
  • 原文鏈接:http://blog.csdn.net/zhangerqing http://www.cnblogs....
    孤獨雜貨鋪閱讀 1,515評論 0 3
  • 設(shè)計模式匯總 一昧旨、基礎(chǔ)知識 1. 設(shè)計模式概述 定義:設(shè)計模式(Design Pattern)是一套被反復(fù)使用拾给、多...
    MinoyJet閱讀 3,937評論 1 15
  • 整體Retrofit內(nèi)容如下: 1、Retrofit解析1之前哨站——理解RESTful 2兔沃、Retrofit解析...
    隔壁老李頭閱讀 3,236評論 2 10
  • 我的母親蒋得,感謝您懷胎十月生下了我。 我的母親乒疏,感謝您這么多年養(yǎng)育了我额衙。 我的母親,感謝您把您女兒嫁個了我怕吴。 母親窍侧,...
    君子有終閱讀 384評論 0 2