設(shè)計模式一代理模式

隨筆記:設(shè)計模式一代理模式
感謝:https://juejin.im/post/5d7c6bc7f265da03f3338254

介紹

代理模式 (Proxy Pattren) 也稱為委托模式蒿柳,是屬于結(jié)構(gòu)型設(shè)計模式,其重要性不言而喻,相信在看過本篇文章之后會發(fā)現(xiàn)不少設(shè)計模式中都有代理模式的影子佛寿。那么何為代理模式串前?其實(shí)代理在我們?nèi)粘I钪胁⒉簧僖娚⒊常瑢τ诔绦騿T來說最常接觸的莫過于代理上網(wǎng)了十籍,連上代理服務(wù)器地址见剩,就可以輕松暢游全世界的網(wǎng)絡(luò)蓬衡;總而言之喻杈,也許你并不留意,但是代理是無處不在狰晚,現(xiàn)實(shí)生活如此筒饰,我們的 Code 世界里也是如此!既然這樣壁晒,我們來探究下代理模式倒是有多普遍瓷们。下面首先看下代理模式的定義吧。

定義

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

使用場景

當(dāng)無法或不想直接訪問某個對象存在困難時可以通過一個代理對象來間接訪問谬晕,為了保證客戶端使用的透明性,委托對象與代理對象需要實(shí)現(xiàn)相同的接口携取。

UML 類圖

image.png
  • Subject: 抽象主題類攒钳;該類的主要職責(zé)是聲明真實(shí)主題與代理的共同接口方法,該類既可以是一個抽象類也可以是一個接口雷滋。
  • RealSubject: 真實(shí)主題類不撑;該類也稱為被委托類或被代理類,該類定義了代理所表示的真實(shí)對象晤斩,由其執(zhí)行具體的業(yè)務(wù)邏輯方法焕檬,而客戶類則通過代理類間接地調(diào)用真實(shí)主題中定義的方法。
  • ProxySubject: 代理類澳泵;該類也稱為委托類或代理類实愚,該類持有一個對真實(shí)主題類的引用,在其所實(shí)現(xiàn)的接口方法中調(diào)用真實(shí)主題類中相應(yīng)的接口方法執(zhí)行,以此起到代理的作用爆侣。
  • Client: 客戶類萍程,即使用代理類的類型。

代碼示例

代理模式可以大致分為兩大部分兔仰,一是靜態(tài)代理茫负,而是動態(tài)代理。靜態(tài)代理是只有具體的代理對象乎赴,而動態(tài)代理則與靜態(tài)代理相反忍法,通過反射機(jī)制動態(tài)地生成代理者的對象,也就是說我們在 code 階段壓根不需要知道代理對象是誰榕吼,代理誰將會在執(zhí)行階段決定饿序。下面我們就來看下吧

簡單示例

靜態(tài)代理

業(yè)務(wù)背景: X 程序員在公司上班時,遇見了公司拖欠工資甚至克扣工資的情況羹蚣,這種情況下 X 程序員還是通過法律途徑來解決問題原探,這個時候就需要請一個律師來作為自己的訴訟代理人,先看下面的代碼示例吧

訴訟接口類:

public interface ILawsuit {

    /**
     * 提交申請
     */
    void submit();

    /**
     * 舉行舉證
     */
    void burden();

    /**
     * 開始辯護(hù)
     */
    void defend();

    /**
     * 訴訟完成
     */
    void finish();
}
復(fù)制代碼

具體訴訟人(X程序員):

public class XProgrammer implements ILawsuit {
    @Override
    public void submit() {
        System.out.println("老板欠 X 程序員工資顽素,申請仲裁!");

    }

    @Override
    public void burden() {
        System.out.println("這是合同書和過去一年的銀行工資流水");

    }

    @Override
    public void defend() {
        System.out.println("證據(jù)確鑿咽弦!不需要再說什么了!");

    }

    @Override
    public void finish() {
        System.out.println("訴訟成功胁出!判決老板即日起 7 天內(nèi)結(jié)算工資型型!");
    }
}
復(fù)制代碼

X程序員請的律師(代理對象):

public class ProxyLawyer implements ILawsuit {
    /**
     * 持有一個具體被代理者的引用,這里就是 X 程序員全蝶,也可以是其它 Y 程序員 只是具體說明闹蒜。
     */
    private ILawsuit mLawsuit;

    public ProxyLawyer(ILawsuit lawsuit) {
        mLawsuit = lawsuit;
    }

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

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

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

    @Override
    public void finish() {
        mLawsuit.finish();
    }
}
復(fù)制代碼

test:

    @Test
    public void testProxy(){

        //X 程序員
        ILawsuit lawsuit = new XProgrammer();

        //程序員請的律師,把自己的事務(wù)交于律師來處理
        ILawsuit proxyLawyer = new ProxyLawyer(lawsuit);

        //律師開始處理
        proxyLawyer.submit();
        proxyLawyer.burden();
        proxyLawyer.defend();
        proxyLawyer.finish();
    }
復(fù)制代碼

output:

老板欠 X 程序員工資抑淫,申請仲裁!
這是合同書和過去一年的銀行工資流水
證據(jù)確鑿绷落!不需要再說什么了!
訴訟成功丈冬!判決老板即日起 7 天內(nèi)結(jié)算工資嘱函!
復(fù)制代碼

動態(tài)代理

動態(tài)代理其實(shí)也很簡單,Java 給我們提供了一個很便捷的動態(tài)代理接口 InvocationHandler ,實(shí)現(xiàn)該接口需要重寫其調(diào)用方法 invoke埂蕊。

下面我們就上面的示例來稍加改動一下:

動態(tài)代理類(這里可以理解為律師對象)

public class DynamicProxy implements InvocationHandler {

    /**
     * 代理者的引用(這里可以理解為 X 程序員)
     */
    private Object object;

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //通過反射調(diào)用其代理者的方法
        return method.invoke(object,args);
    }
}
復(fù)制代碼

test:

    @Test
    public void testDynamicProxy(){

        //X 程序員
        ILawsuit lawsuit = new XProgrammer();

        //構(gòu)造一個動態(tài)代理對象(程序員請的律師往弓,把自己的事務(wù)交于律師來處理)
        DynamicProxy dynamicProxy = new DynamicProxy(lawsuit);

        //拿到代理者身上的 ClassLoader
        ClassLoader classLoader = lawsuit.getClass().getClassLoader();

        //動態(tài)的構(gòu)造一個代理者律師出來
        ILawsuit proxyLawyer = (ILawsuit) Proxy.newProxyInstance(classLoader, new Class[]{ILawsuit.class}, dynamicProxy);

        //律師開始處理
        proxyLawyer.submit();
        proxyLawyer.burden();
        proxyLawyer.defend();
        proxyLawyer.finish();
    }
復(fù)制代碼

output:

老板欠 X 程序員工資,申請仲裁!
這是合同書和過去一年的銀行工資流水
證據(jù)確鑿蓄氧!不需要再說什么了函似!
訴訟成功!判決老板即日起 7 天內(nèi)結(jié)算工資喉童!
復(fù)制代碼

運(yùn)行結(jié)果和靜態(tài)代理一樣撇寞,由此可見動態(tài)代理通過一個代理類來代理 N 多個被代理類,其本質(zhì)是對代理者與被代理者進(jìn)行解耦,使兩者沒有直接的耦合關(guān)系蔑担。相對而言靜態(tài)代理則是能為給定接口下的實(shí)現(xiàn)類做代理牌废,如果接口不同那么就需要重新定義不同的代理類,最為復(fù)雜啤握,但是靜態(tài)代理更符合面向?qū)ο笤瓌t鸟缕。在開發(fā)時具體使用哪種方式來實(shí)現(xiàn)代理,就看自己的偏好了排抬。

總結(jié)

代理模式應(yīng)用廣泛懂从,在后面的結(jié)構(gòu)型模式中,你都可以看到代理模式的影子蹲蒲,有些模式單獨(dú)作為一種設(shè)計模式番甩,倒不如說是對代理模式的一種針對性優(yōu)化。而且代理模式幾乎沒有缺點(diǎn)可言届搁,它是細(xì)分化至很小的一種模式缘薛,如果非得說一個缺點(diǎn)的話,那么就是設(shè)計模式的通病卡睦,對類的增加掩宜。不過在這種孰優(yōu)孰劣的局勢下,就算對類的稍微增加又有什么問題呢么翰,是吧?

作者:DevYK
鏈接:https://juejin.im/post/5d7c6bc7f265da03f3338254
來源:掘金
著作權(quán)歸作者所有辽旋。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)浩嫌,非商業(yè)轉(zhuǎn)載請注明出處。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末补胚,一起剝皮案震驚了整個濱河市码耐,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌溶其,老刑警劉巖骚腥,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異瓶逃,居然都是意外死亡束铭,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進(jìn)店門厢绝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來契沫,“玉大人,你說我怎么就攤上這事昔汉⌒竿颍” “怎么了?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長会通。 經(jīng)常有香客問我口予,道長,這世上最難降的妖魔是什么涕侈? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任沪停,我火速辦了婚禮,結(jié)果婚禮上驾凶,老公的妹妹穿的比我還像新娘牙甫。我一直安慰自己,他們只是感情好调违,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布窟哺。 她就那樣靜靜地躺著,像睡著了一般技肩。 火紅的嫁衣襯著肌膚如雪且轨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天虚婿,我揣著相機(jī)與錄音旋奢,去河邊找鬼。 笑死然痊,一個胖子當(dāng)著我的面吹牛至朗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播剧浸,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼锹引,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了唆香?” 一聲冷哼從身側(cè)響起嫌变,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎躬它,沒想到半個月后腾啥,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡冯吓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年倘待,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片桑谍。...
    茶點(diǎn)故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡延柠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出锣披,到底是詐尸還是另有隱情贞间,我是刑警寧澤贿条,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站增热,受9級特大地震影響整以,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜峻仇,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一公黑、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧摄咆,春花似錦凡蚜、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至涩金,卻和暖如春谱醇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背步做。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工副渴, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人全度。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓煮剧,卻偏偏與公主長得像,于是被迫代替她去往敵國和親将鸵。 傳聞我的和親對象是個殘疾皇子轿秧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評論 2 355