Head First設計模式——代理模式
在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物件的建立與銷燬。
代理模式:為另一個物件提供一個替身或佔位符以控制對這個物件的訪問。
使用代理模式建立代表物件,讓代表物件控制某物件的訪問,被代理的物件可以是遠端物件、建立開銷大的物件或者需要安全控制的物件。
&n