1 代理模式定義
定義:給某個對象提供一個代理對象,並由代理對象控制對於原對象的訪問,即客戶不直接操控原對象,而是通過代理對象間接地操控原對象。
本篇文章主要介紹的是靜態代理,關於動態代理請參考:設計模式之動態代理(dynamic proxy)
2 代理模式的作用
- 在某些情況下,一個客戶不想或者不能直接引用另一個對象,而代理對象可以在客戶端和目標對象之間起到中介的作用。
- 通過代理類對原有類進行功能增強,如增加緩存、異常處理、日誌處理等,Spring AOP用的就是(動態)代理模式
3 代理模式一般涉及到的角色有:
- 抽象主題(Subject):聲明真實對象和代理對象的共同接口;
- 代理(Proxy):代理對象角色內部含有對真實對象的引用,從而可以操作真實對象,同時代理對象提供與真實對象相同的接口以便在任何時刻都能代替真實對象。同時,代理對象可以在執行真實對象操作時,附加其他的操作,相當於對真實對象進行封裝。
真實對象(RealSubject):代理角色所代表的真實對象,是我們最終要引用的對象。
4 應用場景舉例:
下面我們就拿用戶買火車票舉一個例子,傳統的火車票購買方式就是去火車站購買,除此之外,我們還可以通過火車票代售點或者12306網站購買,其實這裏的火車票代售點就扮演着代理角色。下面我們通過代碼演示一遍。
我們要購買火車票,就得有人賣票,我們定義一個賣票Subject。
public interface TicketSubject {
public void sell();
}
然後我們定義一個真實對象,傳統的賣票的地方是火車站:
public class TrainStation implements TicketSubject {
public void sell() {
System.out.println("賣出一張票!");
}
}
最後再定義一個代理對象,火車站太遠,我們想從代售點買票,定義一個代售點做代理類:
public class TrainStationProxy implements TicketSubject {
private TrainStation trainStation;//持有真實對象的引用
public TrainStationProxy(TrainStation trainStation){
this.trainStation=trainStation;
}
public void sell() {
System.out.println("歡迎光臨!");
trainStation.sell();//調用真實對象的方法,體現代理行爲
System.out.println("請交手續費!");
}
}
從代理類來看,它和真實對象實現的是同一個主題接口,並且內部還持有真實對象的引用,在自己的方法內調用真實對象的方法,完美的進行了代理,當然代理類可以在自己的方法裏面添加一些額外的功能。
最後,我們測試一下
定義一個買票的人:
public class SomeBody {
private TicketSubject tickSubject;
public void buy(){
tickSubject.sell();
}
public void goToTicketSubject( TicketSubject tickSubject){
this.tickSubject=tickSubject;
}
}
注意,買票人依賴的是接口而不是具體實現類,這樣就可以用代理類替換實際類了。
最後,這個人去代售點買票:
public class TestProxy {
public static void main(String[] args) {
SomeBody someBody=new SomeBody();
TrainStationProxy adaptor=new TrainStationProxy(new TrainStation());
someBody.goToTicketSubject(adaptor);
someBody.buy();
}
}
看一下打印結果:
歡迎光臨!
賣出一張票!
請交手續費!
代理類完成了購票,還增加了收取手續費的功能!
本篇文章主要介紹的是靜態代理,關於動態代理請參考:設計模式之動態代理(dynamic proxy)