1. 程式人生 > 實用技巧 >大話設計模式讀書筆記(代理模式)

大話設計模式讀書筆記(代理模式)

人物:小菜,大鳥

事件:大鳥詢問小菜和嬌嬌約會經過,小菜道出嬌嬌已經有男朋友了,而且還說嬌嬌給他分享了她的戀愛經歷:高中時期,隔壁班男生卓賈易喜歡嬌嬌,卓賈易找了嬌嬌同班男生,同時也是自己好朋友戴勵,不時向嬌嬌送禮物,這樣一來二去,嬌嬌喜歡上了戴勵,戴勵最終和嬌嬌在一起,卓賈易最終為他人做了嫁衣。


大鳥:卓賈易如果直接追嬌嬌,應該怎麼做呢?

小菜的第一次實現(卓賈易直接追嬌嬌)

追求者類:

@Slf4j
public class Pursuit {
    SchoolGirl mm;

    public Pursuit(SchoolGirl mm) {
        this.mm = mm;
    }

    
public void giveFlowers() { log.info(mm.getName() + "送你鮮花"); } public void giveChocolate() { log.info(mm.getName() + "送你巧克力"); } }

被追求者類:

@Data
public class SchoolGirl {
    private String name;
}

客戶端程式碼:

public static void main(String[] args) {
    SchoolGirl jiaojiao 
= new SchoolGirl(); jiaojiao.setName("嬌嬌"); Pursuit zhuojiayi = new Pursuit(jiaojiao); zhuojiayi.giveFlowers(); zhuojiayi.giveChocolate(); }

大鳥:小菜,你這樣寫:Pursuit zhuojiayi = new Pursuit(jiaojiao) 是指卓賈易直接送禮物給嬌嬌,但他們是不認識的,這樣處理不正確

小菜:那如何處理?

大鳥:將戴賈看做是代理

小菜的第二次實現(使用代理追嬌嬌)

使用代理:

@Slf4j
public
class Proxy { SchoolGirl mm; public Proxy(SchoolGirl mm) { this.mm = mm; } public void giveFlowers() { log.info(mm.getName() + "送你鮮花"); } public void giveChocolate() { log.info(mm.getName() + "送你巧克力"); } }

客戶端程式碼:

public static void main(String[] args) {
    SchoolGirl jiaojiao = new SchoolGirl();
    jiaojiao.setName("嬌嬌");
    Proxy daili = new Proxy(jiaojiao);
    daili.giveChocolate();
    daili.giveFlowers();
}

大鳥:你這樣把追求者Pursuit(追求者)換成了daili(代理),就相當於把卓賈易換成了戴勵。也就是說禮物就程式設計戴勵送的了,卓賈易這個人也就不存在了,你需要找追求者和代理相同的地方

小菜:它們都實現了相同的介面

小菜領悟後的第三次實現

代理介面如下:

public interface GiveGift {
    void giveFlowers();
    void giveChocolate();
}

追求者類:

@Slf4j
public class Pursuit implements GiveGift {
    SchoolGirl mm;

    public Pursuit(SchoolGirl mm) {
        this.mm = mm;
    }

    @Override
    public void giveFlowers() {
        log.info(mm.getName() + "送你鮮花");
    }

    @Override
    public void giveChocolate() {
        log.info(mm.getName() + "送你巧克力");
    }
}

代理類:

@Slf4j
public class Proxy implements GiveGift{
Pursuit gg;

public Proxy(SchoolGirl mm) {
gg = new Pursuit(mm);
}

@Override
public void giveFlowers() {
gg.giveFlowers();
}

@Override
public void giveChocolate() {
gg.giveChocolate();
}
}

客戶端如下:

public static void main(String[] args) {
    SchoolGirl jiaojiao = new SchoolGirl();
    jiaojiao.setName("嬌嬌");
    Proxy daili = new Proxy(jiaojiao);
    daili.giveFlowers();
    daili.giveChocolate();
}

代理模式

代理模式:為其他物件提供一種代理以控制對這個物件的訪問

實現方式:有A,B兩個類,B是代理類,定義讓A,B有共同實現的介面或抽象類C,A中是具體的方法,比如送花,然後B裡面提供方法呼叫,這樣代理就可以代替實體

所用場合:

1.遠端代理,也就是為一個物件在不同的地址空間提供區域性代表,這樣可以隱藏一個物件存在於不同地址空間的事實。例如:WebService在.NET中,當應用程式的專案中加入一個web引用,引用一個webService,這是會在專案中生成一個WebReference的資料夾和一些檔案,這就是代理,使得客戶端程式呼叫代理就可以解決遠端訪問的問題

2.虛擬代理,是根據需要建立開銷很大的物件,通過它們來存放例項化需要很長時間的真實物件。比如開啟一個很大的HTML網頁,裡面可能很多文字和圖片,但是你還是可以很快開啟這個網頁,此時你可以看到文字,但是圖片是要一張一張下載才能看到,那些未開啟的圖片框,就是通過虛擬代理代替了真實的圖片,此時代理儲存了真實的圖片路徑和尺寸

3.安全代理,是用來控制真實物件訪問時的許可權。一般用於物件應該有不同訪問許可權的時候

4.智慧指引,指當呼叫真實的物件時,代理處理另外一些事。如計算物件的引用次數,當該物件沒有引用時,可自動釋放

小結:代理模式就是在訪問物件時引入一定程度的間接性,因為這種間接性,可以附加很多用途