代理模式是常用的結(jié)構(gòu)型設(shè)計(jì)模式之一,當(dāng)無(wú)法直接訪問(wèn)某個(gè)對(duì)象或訪問(wèn)某個(gè)對(duì)象存在困難時(shí)可以通過(guò)一個(gè)代理對(duì)象來(lái)間接訪問(wèn),為了保證客戶端使用的透明性,所訪問(wèn)的真實(shí)對(duì)象與代理對(duì)象需要實(shí)現(xiàn)相同的接口。根據(jù)代理模式的使用目的不同,代理模式又可以分為多種類型,例如保護(hù)代理、遠(yuǎn)程代理、虛擬代理、緩沖代理等,它們應(yīng)用于不同的場(chǎng)合,滿足用戶的不同需求。
15.1 代理模式概述
近年來(lái),代購(gòu)已逐步成為電子商務(wù)的一個(gè)重要分支。何謂代購(gòu),簡(jiǎn)單來(lái)說(shuō)就是找人幫忙購(gòu)買所需要的商品,當(dāng)然你可能需要向?qū)嵤┐?gòu)的人支付一定的費(fèi)用。代購(gòu)?fù)ǔ7譃閮煞N類型:一種是因?yàn)樵诋?dāng)?shù)刭I不到某件商品,又或者是因?yàn)楫?dāng)?shù)剡@件商品的價(jià)格比其他地區(qū)的貴,因此托人在其他地區(qū)甚至國(guó)外購(gòu)買該商品,然后通過(guò)快遞發(fā)貨或者直接攜帶回來(lái);還有一種代購(gòu),由于消費(fèi)者對(duì)想要購(gòu)買的商品相關(guān)信息的缺乏,自已無(wú)法確定其實(shí)際價(jià)值而又不想被商家宰,只好委托中介機(jī)構(gòu)幫其講價(jià)或?yàn)槠浯I。代購(gòu)網(wǎng)站為此應(yīng)運(yùn)而生,它為消費(fèi)者提供在線的代購(gòu)服務(wù),如果看中某國(guó)外購(gòu)物網(wǎng)站上的商品,可以登錄代購(gòu)網(wǎng)站填寫(xiě)代購(gòu)單并付款,代購(gòu)網(wǎng)站會(huì)幫助進(jìn)行購(gòu)買然后通過(guò)快遞公司將商品發(fā)送給消費(fèi)者。商品代購(gòu)過(guò)程如圖15-1所示:
圖15-1 商品代購(gòu)示意圖
在軟件開(kāi)發(fā)中,也有一種設(shè)計(jì)模式可以提供與代購(gòu)網(wǎng)站類似的功能。由于某些原因,客戶端不想或不能直接訪問(wèn)一個(gè)對(duì)象,此時(shí)可以通過(guò)一個(gè)稱之為“代理”的第三者來(lái)實(shí)現(xiàn)間接訪問(wèn),該方案對(duì)應(yīng)的設(shè)計(jì)模式被稱為代理模式。
代理模式是一種應(yīng)用很廣泛的結(jié)構(gòu)型設(shè)計(jì)模式,而且變化形式非常多,常見(jiàn)的代理形式包括遠(yuǎn)程代理、保護(hù)代理、虛擬代理、緩沖代理、智能引用代理等,后面將學(xué)習(xí)這些不同的代理形式。
代理模式定義如下:
代理模式:給某一個(gè)對(duì)象提供一個(gè)代理或占位符,并由代理對(duì)象來(lái)控制對(duì)原對(duì)象的訪問(wèn)。
Proxy Pattern: Provide a surrogate or placeholder for another object to control access to it.
代理模式是一種對(duì)象結(jié)構(gòu)型模式。在代理模式中引入了一個(gè)新的代理對(duì)象,代理對(duì)象在客戶端對(duì)象和目標(biāo)對(duì)象之間起到中介的作用,它去掉客戶不能看到的內(nèi)容和服務(wù)或者增添客戶需要的額外的新服務(wù)。
15.2 代理模式結(jié)構(gòu)與實(shí)現(xiàn)
15.2.1 模式結(jié)構(gòu)
代理模式的結(jié)構(gòu)比較簡(jiǎn)單,其核心是代理類,為了讓客戶端能夠一致性地對(duì)待真實(shí)對(duì)象和代理對(duì)象,在代理模式中引入了抽象層,代理模式結(jié)構(gòu)如圖15-2所示:
圖15-2 代理模式結(jié)構(gòu)圖
由圖15-2可知,代理模式包含如下三個(gè)角色:
(1) Subject(抽象主題角色):它聲明了真實(shí)主題和代理主題的共同接口,這樣一來(lái)在任何使用真實(shí)主題的地方都可以使用代理主題,客戶端通常需要針對(duì)抽象主題角色進(jìn)行編程。
(2) Proxy(代理主題角色):它包含了對(duì)真實(shí)主題的引用,從而可以在任何時(shí)候操作真實(shí)主題對(duì)象;在代理主題角色中提供一個(gè)與真實(shí)主題角色相同的接口,以便在任何時(shí)候都可以替代真實(shí)主題;代理主題角色還可以控制對(duì)真實(shí)主題的使用,負(fù)責(zé)在需要的時(shí)候創(chuàng)建和刪除真實(shí)主題對(duì)象,并對(duì)真實(shí)主題對(duì)象的使用加以約束。通常,在代理主題角色中,客戶端在調(diào)用所引用的真實(shí)主題操作之前或之后還需要執(zhí)行其他操作,而不僅僅是單純調(diào)用真實(shí)主題對(duì)象中的操作。
(3) RealSubject(真實(shí)主題角色):它定義了代理角色所代表的真實(shí)對(duì)象,在真實(shí)主題角色中實(shí)現(xiàn)了真實(shí)的業(yè)務(wù)操作,客戶端可以通過(guò)代理主題角色間接調(diào)用真實(shí)主題角色中定義的操作。
15.2.2 模式實(shí)現(xiàn)
代理模式的結(jié)構(gòu)圖比較簡(jiǎn)單,但是在真實(shí)的使用和實(shí)現(xiàn)過(guò)程中要復(fù)雜很多,特別是代理類的設(shè)計(jì)和實(shí)現(xiàn)。
抽象主題類聲明了真實(shí)主題類和代理類的公共方法,它可以是接口、抽象類或具體類,客戶端針對(duì)抽象主題類編程,一致性地對(duì)待真實(shí)主題和代理主題,典型的抽象主題類代碼如下:
[csharp]
view plain copyabstract class Subject
{
public abstract void Request();
}
真實(shí)主題類繼承了抽象主題類,提供了業(yè)務(wù)方法的具體實(shí)現(xiàn),其典型代碼如下:
[csharp]
view plain copyclass RealSubject : Subject
{
public override void Request()
{
//業(yè)務(wù)方法具體實(shí)現(xiàn)代碼
}
}
代理類也是抽象主題類的子類,它維持一個(gè)對(duì)真實(shí)主題對(duì)象的引用,調(diào)用在真實(shí)主題中實(shí)現(xiàn)的業(yè)務(wù)方法,在調(diào)用時(shí)可以在原有業(yè)務(wù)方法的基礎(chǔ)上附加一些新的方法來(lái)對(duì)功能進(jìn)行擴(kuò)充或約束,最簡(jiǎn)單的代理類實(shí)現(xiàn)代碼如下:
[csharp]
view plain copyclass Proxy : Subject
{
private RealSubject realSubject = new RealSubject(); //維持一個(gè)對(duì)真實(shí)主題對(duì)象的引用
public void PreRequest()
{
…...
}
public override void Request()
{
PreRequest();
realSubject.Request(); //調(diào)用真實(shí)主題對(duì)象的方法
PostRequest();
}
public void PostRequest()
{
……
}
}
在實(shí)際開(kāi)發(fā)過(guò)程中,代理類的實(shí)現(xiàn)比上述代碼要復(fù)雜很多,代理模式根據(jù)其目的和實(shí)現(xiàn)方式不同可分為很多種類,其中常用的幾種代理模式簡(jiǎn)要說(shuō)明如下:
(1) 遠(yuǎn)程代理(Remote Proxy):為一個(gè)位于不同的地址空間的對(duì)象提供一個(gè)本地的代理對(duì)象,這個(gè)不同的地址空間可以是在同一臺(tái)主機(jī)中,也可是在另一臺(tái)主機(jī)中,遠(yuǎn)程代理又稱為大使(Ambassador)。
(2) 虛擬代理(Virtual Proxy):如果需要?jiǎng)?chuàng)建一個(gè)資源消耗較大的對(duì)象,先創(chuàng)建一個(gè)消耗相對(duì)較小的對(duì)象來(lái)表示,真實(shí)對(duì)象只在需要時(shí)才會(huì)被真正創(chuàng)建。
(3) 保護(hù)代理(Protect Proxy):控制對(duì)一個(gè)對(duì)象的訪問(wèn),可以給不同的用戶提供不同級(jí)別的使用權(quán)限。
(4) 緩沖代理(Cache Proxy):為某一個(gè)目標(biāo)操作的結(jié)果提供臨時(shí)的存儲(chǔ)空間,以便多個(gè)客戶端可以共享這些結(jié)果。
(5) 智能引用代理(Smart Reference Proxy):當(dāng)一個(gè)對(duì)象被引用時(shí),提供一些額外的操作,例如將對(duì)象被調(diào)用的次數(shù)記錄下來(lái)等。
在這些常用的代理模式中,有些代理類的設(shè)計(jì)非常復(fù)雜,例如遠(yuǎn)程代理類,它封裝了底層網(wǎng)絡(luò)通信和對(duì)遠(yuǎn)程對(duì)象的調(diào)用,其實(shí)現(xiàn)較為復(fù)雜。