在HeadFirst設計模式中代理模式用了比較多的篇幅來講解,其中的例子我感覺有些繁瑣,是以我們這篇就不按照慣例用例子來闡述代理模式了。我們直接進入正題,分析模式本身的設計和解決的問題。
遠端代理模式
假如我們有一個系統,能夠調用本地對象,然後将每個請求轉發到遠端對象上進行調用應該如何設計。
在用戶端我們使用客戶輔助對象進行調用,客戶輔助對象進行遠端調用,對于客戶對象來說就像是在調用本地的方法一樣。
在服務端,服務輔助對象從客戶輔助對象中接受請求(socket連接配接),将調用的資訊解包,然後調用真正服務對象上的方法。
我們利用代碼更清楚的看到實作過程和方式,書中利用java的RIM來進行遠端方法調用,我們不必糾結RIM,隻要知道RIM是幫我們實作演出調用處理網絡和I/O代碼。
1、遠端接口
首先我們需要一個接口用于客戶輔助對象和服務輔助對象的統一接口。
public interface MyRemote extends Remote{
public String SayHello() throws RemoteException;
}
Remote 是RIM包中的接口,使用RIM需要實作Remote接口。
2、遠端實作
服務實作遠端接口,也就是用戶端要調用的方法的接口。
public class MyRemoteImpl implements MyRemote{
public String SayHello(){
return "server say hello";
}
}
3、注冊服務
現在我們已經實作了一個遠端服務了,要他能被用戶端遠端調用。就需要将服務執行個體化并注冊到RIM registry中,注冊使用了rmi 中的Naming類的靜态方法rebind()
我們可以直接在遠端服務的main() 方法中注冊就行了。
public static void main(String args[]){
try{
MyRemote service=new MyRemoteImpl();
Naming.rebind("RemoteHello",service);
}catch(Exception ex){
ex.printStackTrace();
}
}
4、用戶端實作
由于第三步我們已有了注冊服務的實作,用戶端要想調用遠端服務就需要通過網絡發現服務并調用。利用Naming.lookup()方法傳回值并将他轉成遠端接口進行調用。
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();
}
}
}
整個執行過程:RIM啟動rmiregistry終端,啟動遠端服務運作到main()方法進行服務注冊。用戶端運作main()方法查找服務傳回Object進行轉換到遠端接口對象,調用接口對象的方法進行代理通路遠端服務。
在上面的代碼中部分代碼不完善隻是講解遠端帶來和過程,同樣的.Net 實作遠端代理的一個經典用例就是WCF,看看WCF的模式是不是完美契合遠端代理模式。
代理模式
通過遠端代理模式我們已經知道代理模式的概念和一種實作了,遠端代理是一般代理模式的一種實作。因為代理模式包含許多變體,包括一般代理模式、虛拟代理模式、動态代理、緩存代理、同步代理等等。
這個類圖是一般代理模式的類圖。
首先Subject,它為RealSubject和Proxy提供了接口。通過實作同一接口,Proxy在RealSubject出現的地方取代它。
RealSubject是真正做事情的對象,它是被Proxy代理和控制通路的對象。
Proxy持有RealSubject的引用。在某些時候,Proxy還會負責RealSubjext對象的建立與銷毀。
代理模式:為另一個對象提供一個替身或占位符以控制對這個對象的通路。
使用代理模式建立代表對象,讓代表對象控制某對象的通路,被代理的對象可以是遠端對象、建立開銷大的對象或者需要安全控制的對象。
作者:SunSpring
出處:https://www.cnblogs.com/SunSpring/p/12372689.html
本文版權歸作者所有,歡迎轉載,但未經作者同意需在文章頁面明顯位置給出原文連結。