學(xué)習(xí)設(shè)計(jì)模式之proxy模式
Posted on 2005-08-19 16:58 柳隨風(fēng) 閱讀(937) 評(píng)論(0) 編輯 收藏 所屬分類: java基礎(chǔ)前言: 本文只是本人的學(xué)習(xí)總結(jié),目的希望能和大家一起交流分享,順便備忘,如有不正確的地方,歡迎指正。本文可能需要你對(duì)webwork框架有一定的了解。
我們?cè)陂_(kāi)發(fā)中Proxy模式是經(jīng)常用到的,代理主要用來(lái)對(duì)訪問(wèn)的資源進(jìn)行權(quán)限控制以及監(jiān)控的目的,如果我們?cè)陂_(kāi)發(fā)系統(tǒng)需要對(duì)訪問(wèn)的對(duì)象進(jìn)行控制和監(jiān)控的話,proxy模式是很有用途的。
舉些例子:
我們開(kāi)發(fā)一個(gè)應(yīng)用系統(tǒng)時(shí),用戶請(qǐng)求任何頁(yè)面都要經(jīng)過(guò)權(quán)限控制,最早開(kāi)發(fā)的時(shí)候我們常常封裝一個(gè)權(quán)限驗(yàn)證方法,然后在每個(gè)jsp或者對(duì)應(yīng)的servlet中增加相關(guān)代碼,但是用戶對(duì)權(quán)限的需求往往是多變的,這樣一旦權(quán)限驗(yàn)證方法變化(參數(shù)變化,增加方法),如果開(kāi)發(fā)的系統(tǒng)很龐大的話,有可能你就需要修改幾百個(gè)jsp頁(yè)面或者servlet代碼。
還有我們常需要判斷session是否過(guò)期,如果過(guò)期就要重新登陸系統(tǒng),如果每個(gè)頁(yè)面或者servlet都要加判斷代碼,那也是件比較痛苦的事情。
如果我們采用代理模式,增加Proxy對(duì)象,每次用戶請(qǐng)求必須通過(guò)proxy對(duì)象處理,由它專門處理相關(guān)權(quán)限控制,一旦權(quán)限需求變化了,只需要修改Proxy對(duì)象相關(guān)的實(shí)現(xiàn)方法。
Proxy模式不僅僅用于上述場(chǎng)景,還可以在其他方面應(yīng)用。
我們可以研究研究webwork的源代碼,看看它是如何設(shè)計(jì)的。
webwork開(kāi)發(fā)框架目前是比較流行的web開(kāi)發(fā)框架之一,最近我的開(kāi)發(fā)項(xiàng)目就采用了該框架,它相比struts有很多優(yōu)點(diǎn)(晚出來(lái)的再?zèng)]優(yōu)點(diǎn)也不行啊,呵呵,關(guān)于其缺點(diǎn)也有,有時(shí)間再說(shuō)),
主要如下:
1、 易單元測(cè)試;
2、 線程安全;
3、 允許使用截取器模塊化前/后處理. 攔截器可以通過(guò)配置動(dòng)態(tài)添加, 兩者之間沒(méi)有任何耦合;
4、 WebWork 2使用Ognl, 強(qiáng)大的表達(dá)式語(yǔ)言, 也可以訪問(wèn)值棧. Ognl對(duì)集合和索引屬性的支持非常強(qiáng)大。
其中優(yōu)點(diǎn)3的實(shí)現(xiàn)和proxy模式是非常相關(guān)的,下面就講講webwork如何采用Proxy模式實(shí)現(xiàn)其優(yōu)點(diǎn)3的。
首先我們看看webwork的核心類ServletDispatcher的請(qǐng)求處理代碼:






























.可以看到整個(gè)對(duì)請(qǐng)求的處理非常簡(jiǎn)練:通過(guò)工廠方法獲取一個(gè)ActionProxy 實(shí)例,執(zhí)行ActionProxy實(shí)例的execute()方法,所有請(qǐng)求都需要通過(guò)該方法處理。
ActionProxyFactory.getFactory().createActionProxy(namespace, actionName, extraContext);
這段代碼調(diào)用過(guò)程我簡(jiǎn)單描述一下:
首先ActionProxyFactory.getFactory().獲取到一個(gè)DefaultActionProxyFactory實(shí)例,然后該工廠實(shí)例調(diào)用createActionProxy(相關(guān)參數(shù))方法創(chuàng)建一個(gè)DefaultActionProxy示例。
下面我們看看這個(gè)DefaultActionProxy究竟是如何處理的:
首先它會(huì)根據(jù)相關(guān)信息獲取當(dāng)前Action配置對(duì)象,從中可以知道當(dāng)前Action中配置了那些攔截器、Result等等配置信息,具體可以查看ActionConfig對(duì)象,然后創(chuàng)建一個(gè)調(diào)用對(duì)象DefaultActionInvocation實(shí)例(也是通過(guò)工廠方法),該實(shí)例調(diào)用invoke()方法完成該action配置的攔截器的攔截方法以及action的execute()方法或action自定義的method的執(zhí)行。






















































而一般攔截器對(duì)象都是AroundInterceptor的子類,在AroundInterceptor類中的攔截方法如下:










注意該調(diào)用對(duì)象的invoke方法比較有意思,它采用的是遍歷調(diào)用的方式,每個(gè)Action一般都有多個(gè)攔截器,每個(gè)攔截器執(zhí)行完畢后再回調(diào)該調(diào)用對(duì)象的invoke方法,有點(diǎn)像鏈?zhǔn)剑绻虚g有自定義攔截器有發(fā)現(xiàn)異常,不要再執(zhí)行下去,直接返回Result相關(guān)字符串,中斷之后的攔截器以及Action不再執(zhí)行,正常情況下鏈尾是調(diào)用對(duì)應(yīng)Action實(shí)例的execute()方法,獲取Result相關(guān)字符串后,根據(jù)字符串值獲取相關(guān)Result實(shí)例,執(zhí)行Result實(shí)例中excute()方法派發(fā)或者重導(dǎo)向到相關(guān)視圖(jsp、vm等等),一旦鏈尾處理過(guò)請(qǐng)求后,鏈中的其他節(jié)點(diǎn)就不需要再派發(fā)。只需繼續(xù)執(zhí)行攔截器中的after()方法(如果有的話)的執(zhí)行,webwork采用這樣的方式實(shí)現(xiàn)主要是為了滿足action后處理功能的需要(有點(diǎn)跑題了,變成webwork框架源碼分析)。
題外話:從整個(gè)調(diào)用過(guò)程我們可以發(fā)現(xiàn): Webwork框架的核心功能實(shí)際上都是在Xwork框架中實(shí)現(xiàn)的,Webwork實(shí)際上只是Xwork在B/S系統(tǒng)上的應(yīng)用。
結(jié)束總結(jié):
1、我們?cè)陂_(kāi)發(fā)時(shí),如果要對(duì)訪問(wèn)的對(duì)象進(jìn)行統(tǒng)一預(yù)處理、控制、監(jiān)控管理時(shí)可以采用Proxy模式。
2、Proxy模式往往和Factory模式一起使用。個(gè)人理解是因?yàn)榭紤]系統(tǒng)的擴(kuò)展性、通用性,有可能有不同的類型的Proxy以及調(diào)用,根據(jù)不同的應(yīng)用場(chǎng)景,可以采用不同的工廠創(chuàng)建。
3、如果運(yùn)用的不是很恰當(dāng)?shù)脑挘瑫?huì)造成Proxy的實(shí)現(xiàn)很龐大,并且和相關(guān)對(duì)象耦合過(guò)高,而webwork采用配置每個(gè)action對(duì)應(yīng)的攔截器這種設(shè)計(jì)就非常好,耦合也比較低,實(shí)際上它變相的實(shí)現(xiàn)了每個(gè)對(duì)象采用不同的Proxy,個(gè)人感覺(jué)其這方面的設(shè)計(jì)很不錯(cuò),可以借鑒。