設(shè)計(jì)模式大總結(jié)(二):代理模式

前言#

昨天已經(jīng)簡單的介紹了組合模式,今天再說一下代理模式。

代理模式也有很多種,例如直接代理,組合代理等等,但是中心思想就是保護(hù)被代理的類,這就是組合模式和代理的根本區(qū)別。

正文#

什么代理呢?

這個(gè)就完全不用解釋,每天我們都要遇到這類人:房產(chǎn)中介,旅游中介,婚姻中介等等,他們從提供服務(wù)的客戶得到對(duì)象的授權(quán),然后再對(duì)外提供這種服務(wù),代理就是中介。

首先看看什么是直接代理:

例如:我們聘請(qǐng)了律師幫我們打官司,這樣我們就不必和一些相關(guān)的機(jī)構(gòu)或人有過多的接觸,跟打官司有關(guān)的時(shí)候被律師全部代理負(fù)責(zé),保護(hù)我們自己的權(quán)益。

那么代碼就可以這么寫:

/**
* 代理類
* 返回代理對(duì)象
*/
public class MyProxy{
    // 持有被代理類的對(duì)象
    private My my;

    public MyProxy(){
        my = new My();
    }

    /**
    * 被代理對(duì)象是私有類,外部無法直接訪問
    */
    private class My{
        ...
    }
    
    /**
    * 調(diào)用的是被代理類的方法,可以添加自己的邏輯
    */
    public void Study(){
        my.study();
    }
    ...
}

這種方式有什么好處呢?

始終無法直接操作被代理類,完全被保護(hù),并且被代理類可以選擇不開放某些api。

如果是私密性非常高的類,絕對(duì)不允許私自修改的,那么肯定是需要考慮代理模式。

接下來再看看組合代理:

馬上就周末了,我們準(zhǔn)備出去旅游,計(jì)劃是這樣的:
1、早上出發(fā),旅游各種景點(diǎn)(需購買門票)。
2、中午吃飯(好不容易出去一趟,估計(jì)得提前預(yù)定)。
3、找一個(gè)高檔酒店,美美的睡一覺。

計(jì)劃完美,首先創(chuàng)建幾個(gè)類:

/**
 * Created by li.zhipeng on 2017/7/27.
 *
 *      酒店類
 */
public class Hotel {

    private static Hotel instance;

    private Hotel(){

    }

    public static Hotel getInstance(){
        if (instance == null){
            instance = new Hotel();
        }
        return instance;
    }

    /**
     * 預(yù)定方法
     * */
    public String reserve(){
        return "預(yù)定酒店...\n";
    }

    /**
     * 睡覺
     * */
    public String sleep(){
        return "酒店的床又大又舒服哦~\n";
    }

}
/**
 * Created by li.zhipeng on 2017/7/27.
 *
 *      餐廳類
 */

public class Restaurant {

    private static Restaurant instance;

    private Restaurant(){

    }

    public static Restaurant getInstance(){
        if (instance == null){
            instance = new Restaurant();
        }
        return instance;
    }


    /**
     * 預(yù)定方法
     * */
    public String reserve(){
        return "預(yù)定飯店...\n";
    }

    /**
     * 吃飯
     * */
    public String eat(){
        return "這里的食物棒棒噠~\n";
    }
}
/**
 * Created by li.zhipeng on 2017/7/27.
 *
 *      游玩的地方
 */

public class PlayGround {

    private static PlayGround instance;

    private PlayGround(){

    }

    public static PlayGround getInstance(){
        if (instance == null){
            instance = new PlayGround();
        }
        return instance;
    }

    /**
     * 預(yù)定方法
     * */
    public String reserve(){
        return "購買游玩門票...\n";
    }

    /**
     * 游玩
     * */
    public String play(){
        return "玩的好開森~\n";
    }
}

地方我們都已經(jīng)找好了,于是到了周末準(zhǔn)備出發(fā):

/**
     * 開始游玩
     * */
    public String startPlay(){
        StringBuilder sb = new StringBuilder();
        // 購買游玩門票
        sb.append(PlayGround.getInstance().reserve());
        // 開始游玩
        sb.append(PlayGround.getInstance().play());
        // 飯店預(yù)定
        sb.append(Restaurant.getInstance().reserve());
        // 開始吃飯
        sb.append(Restaurant.getInstance().eat());
        // 酒店預(yù)定
        sb.append(Hotel.getInstance().reserve());
        // 開始睡覺
        sb.append(Hotel.getInstance().sleep());
        return sb.toString();

    }

雖然計(jì)劃是順利執(zhí)行,但是感覺不太完美:

1、旅游景點(diǎn)還得現(xiàn)排隊(duì)買票(浪費(fèi)時(shí)間)。
2、吃飯還得看著時(shí)間提前預(yù)定。
3、酒店差點(diǎn)客滿,沒地方住。

第二次又準(zhǔn)備出去旅游了,吸取上一次的教訓(xùn),我下載了攜程旅游app(雖然我沒怎么用過),直接一條龍服務(wù):

/**
 * Created by li.zhipeng on 2017/7/27.
 *
 *      旅游中介
 */

public class TravelProxy {

    private static TravelProxy instance;

    private TravelProxy(){

    }

    public static TravelProxy getInstance(){
        if (instance == null){
            instance = new TravelProxy();
        }
        return instance;
    }

    /**
     * 旅游一條龍服務(wù)
     * */
    public void travelOneDragen(){
        // 購買游玩門票
        PlayGround.getInstance().reserve();
        // 飯店預(yù)定
        Restaurant.getInstance().reserve();
        // 酒店預(yù)定
        Hotel.getInstance().reserve();
    }

}

訂票服務(wù)一條龍,我只要負(fù)責(zé)玩就好了,但是app拿出來掃一掃,一路完美:

/**
     * 開始游玩
     */
    public void startPlay() {
        TravelProxy travelProxy = TravelProxy.getInstance();
        // 一條龍服務(wù)
        travelProxy.travelOneDragen();
        // 開始游玩
        PlayGround.getInstance().play();
        // 開始吃飯
        Restaurant.getInstance().eat();
        // 開始睡覺
        Hotel.getInstance().sleep();
    }

以后要是再出去旅游,再使用一次就OK了,省時(shí)省力。

討論#

有些朋友可能要噴我:你這個(gè)組合代理不就是放了幾個(gè)類,往里面塞了一個(gè)方法,和組合模式有什么區(qū)別啊。

別著急,我們把 代理代理組合模式 來做一個(gè)對(duì)比總結(jié)

中心思想

代理模式:保護(hù)被代理的多個(gè)類不被隨意控制,相對(duì)私密性高。
組合模式:僅僅是把多個(gè)類進(jìn)行組合使用,對(duì)私密性沒有提高。

模式的目的

代理模式:最終希望得到的是一個(gè)工具類,一般使用單例模式。
組合模式:最終得到的是一個(gè)新的類,等同于被組合的類的性質(zhì)。

類的擴(kuò)展

代理模式:相對(duì)來說,不太希望被代理發(fā)生巨大的變化,因?yàn)闀?huì)對(duì)業(yè)務(wù)造成影響。
組合模式:不太關(guān)心被組合的類發(fā)生變化,按照需求隨意組合。

耦合性

代理模式:降低使用者和被代理類的耦合性。
組合模式:對(duì)耦合性無影響,因?yàn)槭褂谜咧店P(guān)心組合的結(jié)果,不關(guān)心組合的過程。

總結(jié)#

雖然組合模式和代理模式是有些區(qū)別,其實(shí)也可以看成一種模式的兩種不同形態(tài),設(shè)計(jì)模式從來不是單獨(dú)出現(xiàn)的,例如 代理+ 代理 = ?

當(dāng)然我們還可以在代理模式或者組合模式的基礎(chǔ)上繼續(xù)擴(kuò)展,例如加入工廠模式(為不同類型的設(shè)置代理)等等。

ok,周末要到了,祝大家周末愉快,下次再聊。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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