大話設計模式讀書筆記(代理模式)
人物:小菜,大鳥
事件:大鳥詢問小菜和嬌嬌約會經過,小菜道出嬌嬌已經有男朋友了,而且還說嬌嬌給他分享了她的戀愛經歷:高中時期,隔壁班男生卓賈易喜歡嬌嬌,卓賈易找了嬌嬌同班男生,同時也是自己好朋友戴勵,不時向嬌嬌送禮物,這樣一來二去,嬌嬌喜歡上了戴勵,戴勵最終和嬌嬌在一起,卓賈易最終為他人做了嫁衣。
大鳥:卓賈易如果直接追嬌嬌,應該怎麼做呢?
小菜的第一次實現(卓賈易直接追嬌嬌)
追求者類:
@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 publicclass 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.智慧指引,指當呼叫真實的物件時,代理處理另外一些事。如計算物件的引用次數,當該物件沒有引用時,可自動釋放
小結:代理模式就是在訪問物件時引入一定程度的間接性,因為這種間接性,可以附加很多用途