代理模式
代理模式又稱為委托模式。代理模式從字面上很好理解,有些事情你可以不必親自去做,而是通過更為專業(yè)的人或者機(jī)構(gòu)去做。比如你開公司需要工商注冊。你可以選擇自己去了解相關(guān)的規(guī)章制度,親自跑腿去辦理。也可以通過專業(yè)機(jī)構(gòu)辦理。這樣你就不需要去了解辦理的細(xì)節(jié),只需把材料交給機(jī)構(gòu)。機(jī)構(gòu)會為你完成注冊工作。在這個過程中,機(jī)構(gòu)不但會為你完成機(jī)構(gòu)注冊,而且還有可能為你辦理一些你并不知道的增值服務(wù)。這就是典型的代理模式。
1. 實(shí)現(xiàn)代理模式
我們再看一個生活中的例子。房屋買賣中經(jīng)常會出現(xiàn)代理的情況。當(dāng)賣家不在房屋所在地時,可能會委托自己的親人或者朋友進(jìn)行交易。而買方會和代理人直接進(jìn)行交易。交易中間的問題代理人會回答,手續(xù)代理人會辦理。如下圖:
這個代理人不太老實(shí),私自加了20萬,想賺差價(jià)。所以不要以為代理人真的只是代理,在這個過程中他可以加入自己的邏輯處理。而客戶和被代理人并不知道。
我們看看采用代理模式如何實(shí)現(xiàn)這個場景。
首先真正賣掉房子的還是房主,只不過和買房人直接進(jìn)行買賣的是代理人。那么房主和代理人有一個公共的行為都是賣房。那么我們可以抽象出一個接口定義賣房的行為。房主和代理人都需要實(shí)現(xiàn)這個接口。真正的賣房邏輯在房主的實(shí)現(xiàn)中,代理人的賣房實(shí)現(xiàn)只是調(diào)用房主的實(shí)現(xiàn)而已。要達(dá)到這個目的,代理人需要持有房主的引用。而買方進(jìn)行買賣的時候,僅和代理人打交道。不用知道房主是誰,也不用讓房主到現(xiàn)場過戶。甚至連房主身在何處都不知道。
上面其實(shí)就是這個例子的程序設(shè)計(jì)。代碼如下:
房屋交易接口代碼:
public interface RealEstate {
void sell();
}
房主代碼:
public class Seller implements RealEstate {
@Override
public void sell() {
System.out.println("賣了房子");
}
}
代理人代碼:
public class SellerProxy implements RealEstate{
private Seller seller;
@Override
public void sell() {
if(seller==null){
seller = new Seller();
}
seller.sell();
System.out.println("退稅辦理完畢");
}
}
類圖:
代理人在這里有什么用處呢?沒有代理人,直接和房主買就好了啊?試想下,假如現(xiàn)在有了新的買房政策,交易完成后可以退稅,那么在不修改房主代碼的前提下,我們只需要修改此代理人的代碼即可。如果在其他地方賣房沒有此政策,只需要定義另外一個地區(qū)的代理人即可,這里實(shí)現(xiàn)了開閉原則。其實(shí)代理模式還有很多好處和適用的場景。我們下面詳細(xì)來看。
2. 代理模式優(yōu)缺點(diǎn)
2.1 優(yōu)點(diǎn)
代理模式在客戶端代碼和真正的邏輯代碼中引入了一層代理,這樣做有很多好處:代理模式
- 隱藏邏輯的真正實(shí)現(xiàn)對象。上面的例子中,如果賣房人身份特殊,那么通過代理人來賣房,可以不讓買房人接觸到自己;
- 隱藏委托類的某些行為,在代理類認(rèn)為應(yīng)該觸發(fā)時再觸發(fā);
- 代理類可以為委托類的行為附加一些邏輯處理,例如上例中的退稅。
2.2 缺點(diǎn)
- 代理類和委托類實(shí)現(xiàn)同一個接口,因此只能面向接口代理;
- 代理類和委托類實(shí)現(xiàn)同一個接口。即使代理類只想代理某個行為,也需要實(shí)現(xiàn)接口所有方法;
- 代理類和委托類需要一一對應(yīng)。如果你有段邏輯需要對所有的方法都附加上,靜態(tài)代理是無法實(shí)現(xiàn)的。
3. 代理模式適用場景
針對代理模式的三個優(yōu)點(diǎn),我們來看看有哪些適用場景。
- 遠(yuǎn)程調(diào)用代理:在分布式系統(tǒng)中,我們經(jīng)常會調(diào)用其他系統(tǒng)的服務(wù)。通過代理模式,可以對客戶端代碼隱藏遠(yuǎn)程調(diào)用的細(xì)節(jié);
- 虛代理:有一個典型的場景,加載一個包含大量大 size 圖片的頁面時,為了更好的用戶體驗(yàn),可以通過圖片代理類先把圖片的位置占好,保證排版的正確。當(dāng)滾動到某個圖片位置的時候才去加載圖片;
- 保護(hù)代理:當(dāng)委托對象需要訪問權(quán)限控制時,可以通過代理類來控制權(quán)限進(jìn)行保護(hù);
- 智能指引:為委托對象增加一層控制。比如記錄訪問次數(shù),當(dāng)為 0 的時候,可以釋放掉。第一次引用一個對對象時,把它裝入內(nèi)存。訪問委托對象前,檢查是否已經(jīng)有其他訪問已經(jīng)鎖定了它,以確保其他對象不能改變它。
4. 小結(jié)
代理模式由 Suject
接口,RealSubject
實(shí)現(xiàn)和 Proxy
類構(gòu)成。Proxy
類同樣要實(shí)現(xiàn) Suject
接口。同時 Proxy
類依賴 RealSubject
類。代理模式對方的調(diào)用增加了間接性。利用間接性,可以加入額外的邏輯。這也是我們常說的 AOP,即面向切面編程。