大家好,上一篇博客講到了裝飾器模式,而這一篇,我們要講到代理模式。這篇代理模式醞釀了好久。爲什麼呢?因爲我在寫這些模式系列的博客中,都會先閱讀網上的介紹這些模式的博客,看看別人是怎麼寫的,有什麼問題別人是還沒有解釋清楚的,有什麼我是可以補充並且增加的,或者換一種介紹的方式。從而寫出具有自己特色的,有價值的博客。
有一些代理模式的文章舉的例子很像裝飾器模式,所以很多人會在評論下面留言說,樓主寫的不就是裝飾器模式嗎?並不是代理模式吧,懷着這個疑問,我看了很多文章,好像找到一點感覺,但是又好像不夠確定。於是我想起來之前看過的一本書《大話設計模式》,終於在這個書裏面確定了自己的思路。
首先,代理模式是有靜態代理模式和動態代理模式之分的。網上的大部分爭議來自於靜態代理模式。很多人說其他博主舉的例子是裝飾模式,不是代理模式。那倒是是裝飾還是代理呢?我們先來拿買火車票來舉例子吧,因爲現實中,不少人是得靠黃牛刷票纔買的到過年回家的票的。手動笑哭~
先寫一個買票的接口吧。
public interface IBuyTicket {
void buyTicket();
}
然後我們寫一個實現類:
public class BuyTicket implements IBuyTicket {
@Override
public void buyTicket() {
System.out.println("買過年回家的票");
}
}
然後關鍵就到了我們的代理類怎麼寫了:
public class ProxyOfBuyTicket implements IBuyTicket{
//private BuyTicket buyTicket;①
private IBuyTicket iBuyTicket;
/*public ProxyOfBuyTicket(BuyTicket buyTicket) {
this.buyTicket = buyTicket;①
}*/
public ProxyOfBuyTicket(IBuyTicket iBuyTicket){
this.iBuyTicket = iBuyTicket;
}
@Override
public void buyTicket() {
System.out.println("黃牛拿了你的車票錢和代買費");
//buyTicket.buyTicket();①
iBuyTicket.buyTicket();
System.out.println("黃牛把票給你");
}
}
在這個代理類中,我們先是讓它和之前的 BuyTicket類一樣都實現了買票的接口IBuyTicket。然後再把接口定義爲屬性。實現接口的方法。而有爭議的代碼我也寫出來了,也就是註釋掉的代碼。我們可以看到,區別就在於一個是把接口做爲了屬性,一個把對象作爲屬性。我們來寫下主方法輸出。
public class ProcessOfBuyTicket {
public static void main(String[] args) {
BuyTicket buyTicket = new BuyTicket();
ProxyOfBuyTicket proxyOfBuyTicket = new ProxyOfBuyTicket(buyTicket);
proxyOfBuyTicket.buyTicket();
}
}
輸出結果爲:.
黃牛拿了你的車票錢和代買費
買過年回家的票
黃牛把票給你
運行下注釋的代碼,替換原來的代碼,就會發現是同樣的輸出結果。但是把對象作爲屬性的就是裝飾器模式了。那爲什麼接口作爲屬性就是代理模式呢?因爲代理模式中的代理類的其實就是幫助任何實現了買票接口的對象進行買票行爲。而如果是註釋的代碼的話,就變成了只對BuyTicket這個類的對象進行代理。那就變成了裝飾器模式了。講到這裏應該明白了吧,其實關鍵就是在於接口。
至於動態代理,是彌補了靜態代理的不足。在這篇文章先暫時不描述了,展開來篇幅過長。以後再介紹。
文末分享一段歌詞:
總有一條蜿蜒在童話鎮裏夢幻的河
分隔了理想分隔現實
又在前方的山口匯合
願走在技術的人們包括我自己,一路向前,奔流不息