在HeadFirst設(shè)計(jì)模式中代理模式用了比較多的篇幅來(lái)講解,其中的例子我感覺(jué)有些繁瑣,所以我們這篇就不按照慣例用例子來(lái)闡述代理模式了。我們直接進(jìn)入正題,分析模式本身的設(shè)計(jì)和解決的問(wèn)題。
遠(yuǎn)程代理模式
假如我們有一個(gè)系統(tǒng),能夠調(diào)用本地對(duì)象,然后將每個(gè)請(qǐng)求轉(zhuǎn)發(fā)到遠(yuǎn)程對(duì)象上進(jìn)行調(diào)用應(yīng)該如何設(shè)計(jì)。
?
在客戶端我們使用客戶輔助對(duì)象進(jìn)行調(diào)用,客戶輔助對(duì)象進(jìn)行遠(yuǎn)端調(diào)用,對(duì)于客戶對(duì)象來(lái)說(shuō)就像是在調(diào)用本地的方法一樣。
在服務(wù)端,服務(wù)輔助對(duì)象從客戶輔助對(duì)象中接受請(qǐng)求(socket連接),將調(diào)用的信息解包,然后調(diào)用真正服務(wù)對(duì)象上的方法。
我們利用代碼更清楚的看到實(shí)現(xiàn)過(guò)程和方式,書(shū)中利用java的RIM來(lái)進(jìn)行遠(yuǎn)程方法調(diào)用,我們不必糾結(jié)RIM,只要知道RIM是幫我們實(shí)現(xiàn)演出調(diào)用處理網(wǎng)絡(luò)和I/O代碼。
1、遠(yuǎn)端接口
?
?首先我們需要一個(gè)接口用于客戶輔助對(duì)象和服務(wù)輔助對(duì)象的統(tǒng)一接口。
public interface MyRemote extends Remote{ public String SayHello() throws
RemoteException; }
Remote 是RIM包中的接口,使用RIM需要實(shí)現(xiàn)Remote接口。
2、遠(yuǎn)端實(shí)現(xiàn)
服務(wù)實(shí)現(xiàn)遠(yuǎn)端接口,也就是客戶端要調(diào)用的方法的接口。
public class MyRemoteImpl implements MyRemote{ public String SayHello(){
return "server say hello"; } }
3、注冊(cè)服務(wù)
現(xiàn)在我們已經(jīng)實(shí)現(xiàn)了一個(gè)遠(yuǎn)程服務(wù)了,要他能被客戶端遠(yuǎn)程調(diào)用。就需要將服務(wù)實(shí)例化并注冊(cè)到RIM registry中,注冊(cè)使用了rmi
中的Naming類的靜態(tài)方法rebind()
我們可以直接在遠(yuǎn)程服務(wù)的main() 方法中注冊(cè)就行了。
public static void main(String args[]){ try{ MyRemote service=new
MyRemoteImpl(); Naming.rebind("RemoteHello",service); }catch(Exception ex){
ex.printStackTrace(); } }
4、客戶端實(shí)現(xiàn)
由于第三步我們已有了注冊(cè)服務(wù)的實(shí)現(xiàn),客戶端要想調(diào)用遠(yuǎn)端服務(wù)就需要通過(guò)網(wǎng)絡(luò)發(fā)現(xiàn)服務(wù)并調(diào)用。利用Naming.lookup()方法返回值并將他轉(zhuǎn)成遠(yuǎn)端接口進(jìn)行調(diào)用。
public class MyRemoteClient(){ public static void main(String[] args){ new
MyRemoteClient().go(); } public void go(){ try{ MyRemote service=(MyRemote)
Naming.lookup(rmi://127.0.0.1/RemoteHello); String result=service.SayHello();
System.out.println(result); }catch(Exception ex){ ex.printStackTrace(); } } }
整個(gè)執(zhí)行過(guò)程:RIM啟動(dòng)rmiregistry終端,啟動(dòng)遠(yuǎn)端服務(wù)運(yùn)行到main()方法進(jìn)行服務(wù)注冊(cè)。客戶端運(yùn)行main()方法查找服務(wù)返回Object進(jìn)行轉(zhuǎn)換到遠(yuǎn)端接口對(duì)象,調(diào)用接口對(duì)象的方法進(jìn)行代理訪問(wèn)遠(yuǎn)端服務(wù)。
在上面的代碼中部分代碼不完善只是講解遠(yuǎn)程帶來(lái)和過(guò)程,同樣的.Net 實(shí)現(xiàn)遠(yuǎn)程代理的一個(gè)經(jīng)典用例就是WCF,看看WCF的模式是不是完美契合遠(yuǎn)程代理模式。
代理模式
通過(guò)遠(yuǎn)程代理模式我們已經(jīng)知道代理模式的概念和一種實(shí)現(xiàn)了,遠(yuǎn)程代理是一般代理模式的一種實(shí)現(xiàn)。因?yàn)榇砟J桨S多變體,包括一般代理模式、虛擬代理模式、動(dòng)態(tài)代理、緩存代理、同步代理等等。
?
?
?這個(gè)類圖是一般代理模式的類圖。
首先Subject,它為RealSubject和Proxy提供了接口。通過(guò)實(shí)現(xiàn)同一接口,Proxy在RealSubject出現(xiàn)的地方取代它。
RealSubject是真正做事情的對(duì)象,它是被Proxy代理和控制訪問(wèn)的對(duì)象。
Proxy持有RealSubject的引用。在某些時(shí)候,Proxy還會(huì)負(fù)責(zé)RealSubjext對(duì)象的創(chuàng)建與銷毀。
代理模式:為另一個(gè)對(duì)象提供一個(gè)替身或占位符以控制對(duì)這個(gè)對(duì)象的訪問(wèn)。
使用代理模式創(chuàng)建代表對(duì)象,讓代表對(duì)象控制某對(duì)象的訪問(wèn),被代理的對(duì)象可以是遠(yuǎn)程對(duì)象、創(chuàng)建開(kāi)銷大的對(duì)象或者需要安全控制的對(duì)象。
?
熱門工具 換一換
