隨筆-72  評論-20  文章-0  trackbacks-1

          目前大多數(shù)企業(yè)采用J2EE技術(shù)的結(jié)構(gòu)設(shè)計與解決方案。對于我們學(xué)習(xí)和研究J2EE體系結(jié)構(gòu)來說,了解與掌握J(rèn)2EE體系結(jié)構(gòu)的設(shè)計方法及一些常用模式是必須的;模型-視圖-控制(model-view-control,簡稱MVC)結(jié)構(gòu)是目前最常見的J2EE應(yīng)用所基于的體系結(jié)構(gòu),MVC主要適用于交互式的Web應(yīng)用,尤其是存在大量頁面及多次客戶訪問及數(shù)據(jù)顯示;相比較而言,一個工作流體系結(jié)構(gòu)更多應(yīng)用于過程控制和較少交互的情況下;除了體系結(jié)構(gòu)外,J2EE的設(shè)計模式對我們解決應(yīng)用系統(tǒng)的設(shè)計也有很大的幫助。

          一、J2EE的模型-視圖-控制(MVC)體系結(jié)構(gòu)

          模型-視圖-控制結(jié)構(gòu)是交互式應(yīng)用程序廣泛使用的一種體系結(jié)構(gòu)。它有效地在存儲和展示數(shù)據(jù)的對象中區(qū)分功能模塊以降低它們之間的連接度,這種體系結(jié)構(gòu)將傳統(tǒng)的輸入、處理和輸入模型轉(zhuǎn)化為圖形顯示的用戶交互模型,或者換一種說法,是多層次的Web商業(yè)應(yīng)用;MVC體系結(jié)構(gòu)具有三個層面:模型(Model)、視圖(View)和控制(Controller),每個層面有其各自的功能作用,MVC體系結(jié)構(gòu)如下:

          圖1 MVC 體系結(jié)構(gòu)

          模型層負(fù)責(zé)表達(dá)和訪問商業(yè)數(shù)據(jù),執(zhí)行商業(yè)邏輯和操作。也就是說,這一層就是現(xiàn)實生活中功能的軟件模擬;在模型層變化的時候,它將通知視圖層并提供后者訪問自身狀態(tài)的能力,同時控制層也可以訪問其功能函數(shù)以完成相關(guān)的任務(wù)。

          視圖層負(fù)責(zé)顯示模型層的內(nèi)容。它從模型層取得數(shù)據(jù)并指定這些數(shù)據(jù)如何被顯示出來。在模型層變化的時候,它將自動更新。另外視圖層也會將用戶的輸入傳送給控制器。

          控制層負(fù)責(zé)定義應(yīng)用程序的行為。它可以分派用戶的請求并選擇恰當(dāng)?shù)囊晥D以用于顯示,同時它也可以解釋用戶的輸入并將它們映射為模型層可執(zhí)行的操作;在一個圖形界面中,常見的用戶輸入包括點擊按鈕和菜單選擇。在Web應(yīng)用中,它包括對Web層的HTTP GET和POST的請求;控制層可以基于用戶的交互和模型層的操作結(jié)果來選擇下一個可以顯示的視圖,一個應(yīng)用程序通常會基于一組相關(guān)功能設(shè)定一個控制層的模塊,甚至一些應(yīng)用程序會根據(jù)不同的用戶類型具有不同的控制層設(shè)定,這主要是由于不同用戶的視圖交互和選擇也是不同的。

          在模型層、視圖層和控制層之間劃分責(zé)任可以減少代碼的重復(fù)度,并使應(yīng)用程序維護起來更簡單。同時由于數(shù)據(jù)和商務(wù)邏輯的分開,在新的數(shù)據(jù)源加入和數(shù)據(jù)顯示變化的時候,數(shù)據(jù)處理也會變得更簡單。


          二、J2EE設(shè)計模式

          一個設(shè)計模式描述了對于特定設(shè)計問題被驗證的解決方案,它綜合了所有開發(fā)者對這個問題所在領(lǐng)域的知識和見解;同時也是對于常見問題的可重用方案,它們一般適用于單個問題,但是組織在一起就可以提供整個企業(yè)系統(tǒng)的解決方案。下面我們列舉八種常用于J2EE平臺的設(shè)計模式,并對每種模式作簡單的介紹,便于大家學(xué)習(xí)、理解與靈活應(yīng)用。

          1、前控制器

          前控制器(front controller)主要提供一種可以集中式管理請求的控制器,一個前控制器可以接受所有的客戶請求,將每個請求遞交給相應(yīng)的請求句柄,并適當(dāng)?shù)仨憫?yīng)用戶。

          前控制器也是表示層的設(shè)計模式,它的出現(xiàn)主要是由于表示層通常需要控制和協(xié)調(diào)來自不同用戶的多個請求,而這種控制機制又根據(jù)不同的需要,可能會集中式控制或分散式控制。換句話說,就是應(yīng)用系統(tǒng)需要對于表示層的請求提供一個集中式控制模塊,以提供各種系統(tǒng)服務(wù),包括內(nèi)容提取、視圖管理和瀏覽,如果系統(tǒng)中沒有這種集中式控制模塊或控制機制,每個不同的系統(tǒng)服務(wù)都需要進行單獨的視圖處理,這樣代碼的重復(fù)性就會提高,致使系統(tǒng)開發(fā)代價提高;同時,如果沒有一個固定模塊管理視圖之間的瀏覽機制,致使其瀏覽功能下放于每個不同的視圖中,最終必將使得系統(tǒng)的可維護性受到破壞;本文中我們主要討論的是集中式控制模塊,而不是分散式控制,因為前者更適合于大型的應(yīng)用系統(tǒng)。

          基于上面所說的問題,研究人員提出了前控制器的設(shè)計模式。在這種模式中,控制器提供一個處理不同請求的控制點,這里的處理工作包括安全事務(wù)、視圖選擇、錯誤處理和響應(yīng)內(nèi)容的生成;通過將這些處理工作集中在一點進行,大大地減低了Java代碼量,同時這種方法也可以減少在視圖模塊的程序邏輯,保證了在不同請求之間可以重用大量的邏輯代碼。通常,控制器都是和一個分派組件聯(lián)合工作的,分派組件主要是用于視圖管理和瀏覽,也就是為用戶選擇下一個應(yīng)該顯示的視圖,并同時提供對于相關(guān)顯示資源的控制。分派組件可以包含在控制器之內(nèi),或是在另外一個單獨的組件中;雖然前控制器模式推薦對于全部的請求使用統(tǒng)一處理,但是它也沒有限制在一個系統(tǒng)中只能具有一個控制器,在系統(tǒng)中的每個層次都可以具有多個控制器,并且映射至不同的系統(tǒng)服務(wù),下圖2顯示了前控制器的類圖。

          圖2 前控制器的類圖

          圖3顯示了前控制器的序列圖,表示一個控制器如何處理相關(guān)的請求。

          圖3前控制器序列圖

          下面我們來討論一下圖3的各個組件。

          2、控制器

          控制器(controller)是負(fù)責(zé)處理各種客戶請求的控制點,并可以將一定的職能(如用戶認(rèn)證等)下放給幫助類。

          (1)分派組件(Dispatcher)。一個分派組件主要是用于視圖的管理和瀏覽,為用戶選擇下一個可以顯示的視圖,并管理相關(guān)的顯示資源;分派組件可以在一個控制器內(nèi)運行,或者作為一個單獨的組件與控制器協(xié)同工作;開發(fā)人員可以在分派組件中實現(xiàn)靜態(tài)的視圖分派技術(shù),或是復(fù)雜的動態(tài)分派。

          (2)幫助類(Helper)。幫助類負(fù)責(zé)幫助一個視圖或控制器來完成其處理工作,因此,幫助類具有多項職責(zé),包括收集數(shù)據(jù)、存儲中間數(shù)據(jù)模型等;另外,幫助類也可以在保證數(shù)據(jù)完整性和準(zhǔn)確性的情況下,為不同顯示需求修改數(shù)據(jù)模型;也就是說,根據(jù)用戶的請求,幫助類可以向視圖提供未經(jīng)處理的原始數(shù)據(jù),或是已經(jīng)格式化后的Web內(nèi)容,一個視圖同時可以和多個幫助類協(xié)同工作,而后者通常是由JavaBeans和標(biāo)簽(tag)實現(xiàn)的。

          3、視圖    

          視圖(view)負(fù)責(zé)向用戶顯示信息,而幫助類則負(fù)責(zé)支持視圖的工作,即打包和建立相應(yīng)的數(shù)據(jù)模型,下面我們介紹幾種可以實現(xiàn)控制器的方法。

          1)基于Servlet前控制器

          這種方法建議使用servlet來實現(xiàn)一個控制器,盡管在語法上相差無幾,但是它比使用JSP來實現(xiàn)要優(yōu)越一些;因為控制器所進行的請求處理,多數(shù)都是與程序運行和控制流動相關(guān)的,這些處理工作雖然與顯示模式相關(guān),但是實際上是邏輯獨立的,所以它們更適合在servlet中實現(xiàn),而不是JSP技術(shù)中;使用這種方法也存在一些弱點,比如說servlet無法使用JSP運行環(huán)境的資源,如請求參數(shù)等,但是這個弱點也不是不能解決的,我們可以在servlet中建立相關(guān)的句柄來訪問同樣的資源,當(dāng)然其代碼會變得繁瑣一點。

          2)基于JSP的前控制器

          這種方法建議使用JSP頁面實現(xiàn)控制器,盡管語法上相同,但是Servlet方案要比其優(yōu)越一些;因為控制器所處理的邏輯一般都不是有關(guān)顯示模式的,所以在JSP頁面中實現(xiàn)控制器似乎有點風(fēng)馬牛不相及;使用這種方法也不利于開發(fā)團隊的角色和職責(zé)的分配,即軟件開發(fā)人員需要在負(fù)責(zé)顯示邏輯的JSP頁面中修改請求處理的代碼,通常,這種工作都是相當(dāng)復(fù)雜的,尤其考慮整個JSP頁面的編程、編譯、測試和調(diào)試錯誤。

          3)控制器之中的分派組件

          如果分派組件沒有較多功能,開發(fā)人員可以在控制器實現(xiàn)該組件。

          4)基礎(chǔ)前端

          基于使用servlet實現(xiàn)前控制器,這種方案建議實現(xiàn)一個控制器作為基礎(chǔ)類,這樣其他的控制器可以在其之上擴展;這個基礎(chǔ)類可以包含一些通用的邏輯實現(xiàn),它的子類就會重載這些實現(xiàn)代碼,這種方法也有一定的缺陷,當(dāng)有許多子類繼承這個基礎(chǔ)類,并大量地重用代碼時,那么就有可能出現(xiàn)一個類的改變會影響到所有子類的情況。

          5)用過濾器實現(xiàn)前控制器

          過濾器提供了與用戶請求的中心處理相類似的功能,也就是說,控制器的一些功能可以由過濾器來實現(xiàn),這種方案的過濾器主要負(fù)責(zé)處理請求的截取和解釋,而不是請求的處理和響應(yīng)的生成;通??梢詾閼?yīng)用系統(tǒng)提供一個核心控制點,以處理所有的系統(tǒng)服務(wù)和程序邏輯,核心控制也就表明了所有的請求都可以簡單地被跟蹤和記錄,從而方便各種服務(wù)功能的實施;當(dāng)然,它也存在一些缺點,一個核心控制點的小問題可能會引發(fā)系統(tǒng)的崩潰,但在應(yīng)用系統(tǒng)的實際開發(fā)中,這并不是個問題,因為通常我們都會在同一個層面上實現(xiàn)多個控制器,從而避免了這個缺陷;在控制器中,開發(fā)人員可以很方便地實現(xiàn)一個檢查安全機制的組件,從而可以在最外層屏蔽對系統(tǒng)的惡意訪問,另外使用控制器也會提高系統(tǒng)模塊的可重用性,尤其在控制器同時使用幫助類的時候。

          4、視圖幫助

          視圖幫助(View helper)是屬于表示層的設(shè)計模式,一個視圖幫助可以包含相關(guān)視圖中的數(shù)據(jù)訪問和內(nèi)容顯示的邏輯,并可以精煉簡化視圖;顯示邏輯主要是關(guān)于如何格式化頁面上的數(shù)據(jù),而訪問邏輯則是關(guān)于如何取出數(shù)據(jù),視圖幫助通常用來顯示數(shù)據(jù)的JSP標(biāo)記(tag)或是讀取數(shù)據(jù)的JavaBean。

          這種設(shè)計模式的出現(xiàn)主要是由于目前的應(yīng)用系統(tǒng)通常需要實時地開發(fā)顯示內(nèi)容,并且能處理動態(tài)的程序數(shù)據(jù)。如果這些程序數(shù)據(jù)的訪問邏輯和顯示邏輯的關(guān)系過于緊密,則系統(tǒng)的表示層就會經(jīng)常需要改動,從而系統(tǒng)的靈活性、重用性會大大地受到破壞;同時在相同的模塊中實現(xiàn)訪問邏輯和顯示邏輯將會影響系統(tǒng)的模塊化,也會使得開發(fā)團隊的任務(wù)劃分不清。

           一個視圖通常包含格式化信息,并將其處理任務(wù)分發(fā)給自己的幫助類,后者通常是用JavaBeans 或標(biāo)記(tag)來實現(xiàn)的,幫助類同時可以存儲視圖的中間數(shù)據(jù)模型并實現(xiàn)數(shù)據(jù)適配器的功能,即適當(dāng)?shù)剞D(zhuǎn)化數(shù)據(jù)格式;開發(fā)人員可以采用多種方法實現(xiàn)視圖組件,通常,開發(fā)人員可以使用JSP來實現(xiàn),并且這也是一種值得推薦的方法。當(dāng)然,相應(yīng)地開發(fā)人員也可以使用Servlet來實現(xiàn)它,將視圖中一定的程序邏輯植入到幫助類中,會有利于應(yīng)用系統(tǒng)的模塊化和可重用性。系統(tǒng)可以使用同一個幫助類為不同的用戶顯示不同的數(shù)據(jù)信息,并在不同的顯示格式下顯示;通常,如果開發(fā)人員發(fā)現(xiàn)視圖的JSP頁面中存在大量的腳本代碼時,就可以考慮使用視圖幫助這種模式了,因為在這種情況下,基本都是程序邏輯和顯示邏輯具有過于緊密的聯(lián)系;這時開發(fā)人員可以將一些適用于所有類型的請求的邏輯處理放置到一定的幫助類中,而根據(jù)需要,也可以將另外一些邏輯處理放置在視圖層上的其他程序模塊中,比如說以前討論過的截取過濾器。   

          視圖幫助這種模式的設(shè)計理念主要是分離應(yīng)用系統(tǒng)的邏輯職責(zé),下面我們提供一些圖示,以方便大家更好地理解這種模式。

          圖4以類圖(class diagram)的形式說明了視圖幫助的系統(tǒng)結(jié)構(gòu)。

          圖4 視圖幫助類圖

          圖5表示了視圖幫助模式的序列圖,它表明了這種模式中的主要成分及互相之間的運行情況;不過需要說明的是,在很多應(yīng)用系統(tǒng)中,客戶端和視圖層之間會存在一個控制器加以適當(dāng)?shù)恼{(diào)節(jié)。

          圖5視圖幫助序列圖

          在類圖表中,大家可以發(fā)現(xiàn),可能存在沒有任何相關(guān)幫助類的視圖,這種情況下,通常代表視圖的JSP頁面會有一些靜態(tài)的或小數(shù)量的腳本代碼。

          這里我們對于序列圖中的各個元素加以簡單的介紹:

          (1)視圖(view)。視圖負(fù)責(zé)向用戶展示動態(tài)數(shù)據(jù)信息,而幫助類則負(fù)責(zé)支持視圖的工作,即打包和建立相應(yīng)的數(shù)據(jù)模型。

          (2)幫助類(helper)。一個幫助類負(fù)責(zé)幫助視圖或控制器完成相關(guān)的處理工作,包括收集數(shù)據(jù)、存儲中間模型等;幫助類也可以在保證數(shù)據(jù)完整性和準(zhǔn)確性的情況下,為不同顯示需求修改數(shù)據(jù)模型,也就是說,根據(jù)用戶的請求,幫助類可以向視圖提供未經(jīng)處理的原始數(shù)據(jù),或是已經(jīng)格式化后的Web內(nèi)容;一個視圖同時可以和多個幫助類協(xié)同工作,而后者通常是由JavaBeans和標(biāo)記(tag)實現(xiàn)的。

          (3)值bean(ValueBean)。值bean實際上是用于存儲中間數(shù)據(jù)模型的幫助類的另一種叫法,例如在序列圖5中,business service就根據(jù)請求返回了一個值bean。

          (4)業(yè)務(wù)服務(wù)(business service)。業(yè)務(wù)服務(wù)是指用戶試圖得到的,應(yīng)用系統(tǒng)可以提供的相關(guān)服務(wù);通常來說,業(yè)務(wù)服務(wù)可以通過一個業(yè)務(wù)代表(business delegate)來訪問,而后者主要是提供對于業(yè)務(wù)服務(wù)的控制和保護。

          在應(yīng)用系統(tǒng)的視圖模塊中使用幫助類可以將不同的程序邏輯很好地分離開來,并在視圖模塊之外為開發(fā)人員提供設(shè)計程序邏輯的空間;基于JavaBean和標(biāo)記 (tag)所開發(fā)的幫助類通常都可以被多個視圖模塊重用,因此也提高了組件的重用性和可維護性;把顯示邏輯從數(shù)據(jù)處理邏輯分離出來,也有利于開發(fā)團隊中角色及人物的劃分;比如說,如果各種程序邏輯過于結(jié)合的話,軟件開發(fā)人員可能需要在HTML,網(wǎng)頁中修改代碼而Web設(shè)計師則需要在處理數(shù)據(jù)訪問的JSP中修改頁面布置,這些情況都可能會導(dǎo)致系統(tǒng)設(shè)計和開發(fā)中由于不同技術(shù)人員的介入,而產(chǎn)生相關(guān)的問題。

          5、會話面

          會話面(session facade)模式在合作的企業(yè)對象間調(diào)節(jié)操作,并將應(yīng)用函數(shù)合成一個單一簡單的界面;它減少了類之間合作的復(fù)雜性,并使得類的調(diào)用者在該類變化的時候無需改動,這種模式通常以一個會話bean實現(xiàn),以用來隱藏底層ejb的復(fù)雜交互。

          這種設(shè)計模式出現(xiàn)的背景在于EJB通常既包括程序數(shù)據(jù),又包括程序邏輯,而這些代碼都會通過一定的界面作用于客戶層,在多層次的J2EE平臺應(yīng)用程序中,就會造成一定的困難。

          具體來說,在J2EE平臺上的多層次系統(tǒng)中,通常會存在以下的問題:

              (1)層次之間聯(lián)系過于緊密,客戶層和后端的業(yè)務(wù)對象具有較強的依賴關(guān)系;

              (2)在客戶和服務(wù)器之間有多次方法調(diào)用,因而導(dǎo)致了Web性能方面的問題;

              (3)缺乏一定的客戶訪問機制,使得一些后臺對象被隨便訪問。

          一個多層次的J2EE應(yīng)用程序通常具有很多由EJB實現(xiàn)的服務(wù)器端對象,它們通常負(fù)責(zé)提供系統(tǒng)服務(wù)、數(shù)據(jù)信息等,也就是說作為業(yè)務(wù)對象,它們既包括相關(guān)的程序數(shù)據(jù),也包括其程序邏輯;在J2EE應(yīng)用系統(tǒng)中,負(fù)責(zé)程序邏輯的對象通常由會話bean實現(xiàn),而表示持久性存儲,并在多個用戶間共享的對象則由實體 bean來實現(xiàn);當(dāng)然,應(yīng)用系統(tǒng)的用戶需要訪問企業(yè)對象來滿足自己的需求,如果企業(yè)對象向用戶提供接口,用戶可以直接地與相關(guān)對象通信,但是這樣一來,用戶必須負(fù)責(zé)管理所調(diào)用的企業(yè)對象之間的關(guān)系,并且能夠處理其間的業(yè)務(wù)流程;然而,如果用戶和業(yè)務(wù)對象之間存在過于直接的交互,兩者的聯(lián)系就會過于緊密,同時也使得用戶過于依賴企業(yè)對象的具體實現(xiàn),并負(fù)責(zé)管理與交互過程有關(guān)的業(yè)務(wù)對象查找和創(chuàng)建,以及不同的對象間相互調(diào)用的關(guān)系,甚至一些時候用戶還需要管理多次調(diào)用之間的事務(wù)管理環(huán)節(jié)。

          在用戶需求不斷增加時,這也是應(yīng)用系統(tǒng)經(jīng)常發(fā)生的情況,用戶與不同的企業(yè)對象之間的交互也會變得越來越復(fù)雜,而企業(yè)對象可能需要一定內(nèi)部的更新才能滿足前者的需要,但是這樣的話用戶又需要根據(jù)企業(yè)對象實現(xiàn)的變化而做出相應(yīng)的改變,這種情況將為應(yīng)用系統(tǒng)帶來相當(dāng)大的麻煩;在訪問EJB應(yīng)用系統(tǒng)時,用戶需要與遠(yuǎn)程對象進行交互。如果用戶直接與所有相關(guān)的業(yè)務(wù)對象交互的話,將帶來很大的Web負(fù)擔(dān);因為對于每一個ejb的激活,都將產(chǎn)生一次遠(yuǎn)程的調(diào)用,而如果存在大量的系統(tǒng)用戶,用戶與對象間的交互就將為Web通信帶來很大的壓力,使系統(tǒng)性能受到很大破壞;如果用戶可以直接訪問后端的企業(yè)對象,但是系統(tǒng)中又缺少一個統(tǒng)一的用戶訪問機制,那么這些訪問很有可能變得雜亂無章,引起系統(tǒng)性能的下降,甚至導(dǎo)致一些安全問題。

          為了解決以上的問題,開發(fā)人員可以采用會話面的設(shè)計模式,即使用會話bean來實現(xiàn)一個面(facade)來包含一個工作流中所有相關(guān)對象的交互;這個會話面負(fù)責(zé)管理業(yè)務(wù)對象,并向用戶提供一個統(tǒng)一的服務(wù)訪問層,會話面可以面向底層對象的交互過程,并提供一個僅僅包含必須提供的接口的服務(wù)層,由此它將復(fù)雜的對象交互和用戶之間隔離開來;    會話面也負(fù)責(zé)管理企業(yè)數(shù)據(jù)和企業(yè)對象之間的交互,并表達(dá)其中需要的企業(yè)邏輯,因此會話面也可以管理企業(yè)對象之間的作用關(guān)系;同時,根據(jù)工作流的需要,會話面也管理對象的創(chuàng)建、查找、修改和刪除。

          在一個復(fù)雜的應(yīng)用系統(tǒng)中,會話面可以將其生命周期的管理下放到一個單獨的幫助對象去,比如說,會話面可以將管理會話和實體bean生命周期的工作交給服務(wù)定位對象;    同時,在應(yīng)用系統(tǒng)中,檢查業(yè)務(wù)對象之間的作用關(guān)系也是非常重要的,一些關(guān)系可能是暫時的,即只使用于一定的交互過程,而另外一些關(guān)系則是永久的,暫時的關(guān)系適合建模于會話面中的工作流,永久的關(guān)系則需要具體情況具體分析。

          圖6中的類圖簡要描述了會話面的設(shè)計模式,圖7給出了會話面的序列表示,即參與組件及其交互關(guān)系。

          圖6 會話面類圖

          圖7會話面序列圖

          這里我們對于圖7的各個組件加以簡要的介紹:

              (1)客戶(Client)。這表示會話面的客戶,即需要訪問相關(guān)企業(yè)服務(wù)的客戶端應(yīng)用程序,當(dāng)然也可以是在同一層面或不同層面的另外一個會話bean。

              (2)會話面(Session Facade)。會話面通常是用會話bean來實現(xiàn)的,它管理著多個企業(yè)對象的作用關(guān)系并提供一個高層次的抽象界面給用戶。

              (3)業(yè)務(wù)對象(Business Object)。業(yè)務(wù)對象是一個可以使用多個不同設(shè)計方案的對象,例如會話bean、實體bean和數(shù)據(jù)訪問對象。在圖6中業(yè)務(wù)對象負(fù)責(zé)提供數(shù)據(jù)和服務(wù),而會話面則需要與多個業(yè)務(wù)對象實例交互而獲得相應(yīng)的服務(wù)。

          會話面實際上就是業(yè)務(wù)層的一個控制對象,它負(fù)責(zé)控制用戶與企業(yè)數(shù)據(jù)和企業(yè)服務(wù)對象之間的交互;在一個復(fù)雜的應(yīng)用系統(tǒng)中,甚至可能會有多個會話面作為用戶和對象模塊之間的中介。

          下面介紹兩種實現(xiàn)會話面的常見方法。

              (1)無狀態(tài)的會話面

          在實現(xiàn)會話面的時候,首先應(yīng)該決定是用狀態(tài)化還是無狀態(tài)的會話bean來實現(xiàn),這主要取決于會話面所建模的業(yè)務(wù)流程;如果一個業(yè)務(wù)流程只需要一次方法調(diào)用就可以實現(xiàn)其服務(wù),那么就可以使用無狀態(tài)的會話bean來實現(xiàn)它。

              (2)狀態(tài)化的會話面

          當(dāng)一個業(yè)務(wù)流程需要多次方法調(diào)用來實現(xiàn)其服務(wù)時,開發(fā)人員最好使用狀態(tài)化的會話bean來實現(xiàn)這一流程,因為每次方法調(diào)用的狀態(tài)信息都必須在會話bean中保存。

          通過在應(yīng)用系統(tǒng)中采用會話面的設(shè)計模式,將在系統(tǒng)中得到以下的收益:

              ①為用戶提供一個簡單的接口,并隱藏所有與系統(tǒng)組件復(fù)雜的交互過程;

              ②減少暴露給用戶的企業(yè)對象,從而降低它們之間的依賴關(guān)系;

              ③向用戶隱藏系統(tǒng)組件間的交互過程和依賴關(guān)系,從而使得系統(tǒng)更加容易管理,并提供相當(dāng)?shù)撵`活性;提供一套統(tǒng)一的用戶訪問機制,便于管理用戶對于系統(tǒng)服務(wù)的請求與訪問。

          6、數(shù)據(jù)訪問對象

          數(shù)據(jù)訪問對象(data access object,DAO)模式將數(shù)據(jù)訪問邏輯抽象為特殊的資源,也就是說將系統(tǒng)資源的接口從其底層訪問機制中隔離出來;通過將數(shù)據(jù)訪問的調(diào)用打包,數(shù)據(jù)訪問對象可以促進對于不同數(shù)據(jù)庫類型和模式的數(shù)據(jù)訪問。

          這種模式出現(xiàn)的背景在于數(shù)據(jù)訪問的邏輯極大程度上取決于數(shù)據(jù)存儲的格式,比如說關(guān)系型數(shù)據(jù)庫、面向?qū)ο髷?shù)據(jù)庫、磁盤文件等。

          目前大部分的J2EE應(yīng)用程序都需要在一定程度上使用可持久性的數(shù)據(jù),而實現(xiàn)持久性數(shù)據(jù)的方法因應(yīng)用程序不同而異,并且訪問不同存儲格式數(shù)據(jù)的應(yīng)用程序接口(API)也有著顯著的差別;有的時候,應(yīng)用程序還會訪問存儲在不同操作平臺上的數(shù)據(jù),這使得問題更為復(fù)雜,通常,應(yīng)用程序會使用共享的分布式組件,如實體bean來表達(dá)持久性數(shù)據(jù)。應(yīng)用程序可以使用bean管理的持久性實體bean,而在實體bean中植人數(shù)據(jù)訪問邏輯,或者使用容器管理的持久性實體 bean,從而使容器管理所有的事務(wù)和持久性細(xì)節(jié);而如果應(yīng)用程序?qū)τ跀?shù)據(jù)訪問的需求十分簡單的話,也可以采用會話bean或Servlet直接訪問持久性存儲來讀取和修改數(shù)據(jù)。

          一些應(yīng)用程序可以使用JDBC應(yīng)用程序接口來訪問關(guān)系數(shù)據(jù)庫中的數(shù)據(jù),JDBC負(fù)責(zé)一般的持久性數(shù)據(jù)訪問和管理,在J2EE應(yīng)用程序中,JDBC中可以嵌入SQL語句,用以訪問關(guān)系型數(shù)據(jù)庫,當(dāng)然根據(jù)數(shù)據(jù)庫類型的不同,SQL語句的詞法和語法也會有所不同;需要說明的是,當(dāng)數(shù)據(jù)存儲格式不同的時候,數(shù)據(jù)訪問邏輯的區(qū)別就更加明顯了,例如關(guān)系型數(shù)據(jù)庫、面向?qū)ο髷?shù)據(jù)庫和磁盤文件,各自數(shù)據(jù)的訪問邏輯各有千秋,這樣一來就造成了程序代碼和數(shù)據(jù)訪問代碼之間的依賴關(guān)系;當(dāng)程序組件,即實體bean、會話bean或servlet、JSP等需要訪問數(shù)據(jù)源時,它們會使用正確的應(yīng)用程序接口來得到連接并管理數(shù)據(jù)源,但這樣也會造成這些組件與數(shù)據(jù)源物理實現(xiàn)之間的依賴關(guān)系,從而使得應(yīng)用程序很難從一個數(shù)據(jù)存儲實體移植到另一個數(shù)據(jù)存儲實體中去;當(dāng)數(shù)據(jù)源的物理實現(xiàn)變化的時候,應(yīng)用程序也必須相應(yīng)地加以改變。

          基于以上所討論的問題,開發(fā)人員開始采用數(shù)據(jù)訪問對象的方法。數(shù)據(jù)訪問對象實際上就是包含對于所有數(shù)據(jù)訪問邏輯的對象,并管理著對于數(shù)據(jù)源的連接,根據(jù)數(shù)據(jù)源的不同,數(shù)據(jù)訪問對象實現(xiàn)了不同的訪問機制,這里所說的數(shù)據(jù)源可以是持久性存儲介質(zhì),如關(guān)系型數(shù)據(jù)庫,也可以是外部服務(wù),如B2B的數(shù)據(jù)交換;不僅是用戶,而且包括應(yīng)用系統(tǒng)中的其他組件,也可以使用數(shù)據(jù)訪問對象所提供的數(shù)據(jù)訪問接口,數(shù)據(jù)訪問對象將數(shù)據(jù)源的物理實現(xiàn)細(xì)節(jié)與其用戶完全分離開來,并且在底層數(shù)據(jù)源變化的時候,數(shù)據(jù)訪問對象向用戶提供的接口是不會變化的;這種方法使應(yīng)用系統(tǒng)使用數(shù)據(jù)訪問對象時可以適應(yīng)多種數(shù)據(jù)存儲介質(zhì),總之,數(shù)據(jù)訪問對象就是系統(tǒng)組件和數(shù)據(jù)源中間的適配器。

          圖8中的類圖表示了數(shù)據(jù)訪問對象設(shè)計模式的參與對象和之間的調(diào)用關(guān)系,圖9是這種設(shè)計模式的序列圖。

          圖8 數(shù)據(jù)訪問對象類圖

          圖9 數(shù)據(jù)訪問對象序列圖

          對于圖9序列圖中的組件加以解釋如下:

              (1)業(yè)務(wù)對象(Business Object)。表示數(shù)據(jù)的用戶,它需要對于數(shù)據(jù)的訪問,一個業(yè)務(wù)對象可以用會話bean、實體bean或是其他Java程序來實現(xiàn)。

              (2)數(shù)據(jù)訪問對象(Data Access Object)。數(shù)據(jù)訪問對象是這種模式中的主題,它提供了底層數(shù)據(jù)訪問的對象,并將其提供給業(yè)務(wù)對象以使得后者能夠透明地訪問數(shù)據(jù)源;同時業(yè)務(wù)對象也將數(shù)據(jù)的加載和存儲操作移交給數(shù)據(jù)訪問對象處理。

              (3)數(shù)據(jù)源(Data source)。這里指的是數(shù)據(jù)源的物理實現(xiàn),這個數(shù)據(jù)源可以是一個數(shù)據(jù)庫,包括關(guān)系型數(shù)據(jù)庫、面向?qū)ο髷?shù)據(jù)庫或文件系統(tǒng)。

              (4)傳輸對象(Transfer Object)。這里的傳輸對象指的是數(shù)據(jù)載體。數(shù)據(jù)訪問對象可以使用傳輸對象來向用戶返回數(shù)據(jù),而數(shù)據(jù)訪問對象同樣可以從用戶那里得到傳輸對象來對數(shù)據(jù)源中的數(shù)據(jù)進行更新。

          下面給出幾種實現(xiàn)數(shù)據(jù)訪問對象設(shè)計模式的方法。   

              (1)自動數(shù)據(jù)訪問對象代碼的生成

          既然每一個業(yè)務(wù)對象都對應(yīng)于一個數(shù)據(jù)訪問對象,那么開發(fā)人員就可以建立業(yè)務(wù)對象、數(shù)據(jù)訪問對象和底層實現(xiàn)的關(guān)系;一旦這種關(guān)系建立起來,開發(fā)人員就可以為所有的數(shù)據(jù)訪問對象編寫特殊的代碼生成工具。

          生成數(shù)據(jù)訪問對象的信息通常存儲在一個開發(fā)人員定義的描述文件中,如果對于數(shù)據(jù)訪問對象的要求過于復(fù)雜,開發(fā)人員可以考慮使用第三方工具來為關(guān)系型數(shù)據(jù)庫提供對象對關(guān)系的映射。這些工具通常是一些GUI程序,可以用來將業(yè)務(wù)對象映射為持久性的存儲對象,并定義中間運作的數(shù)據(jù)訪問對象,在映射完成的時候,這些工具可以自動地生成代碼,并提供一些相應(yīng)的功能,如緩存結(jié)果、緩存查詢、與應(yīng)用服務(wù)器整合、與第三方產(chǎn)品整合等。

              (2)數(shù)據(jù)訪問對象代理(Factory for Data Access Objects)

          當(dāng)?shù)讓拥臄?shù)據(jù)存儲不會輕易改變的時候,開發(fā)人員可以采取這種方法來實現(xiàn)相應(yīng)的,數(shù)據(jù)訪問對象,圖10是這種方法的類圖。

          圖10 使用DAO代理類圖

          當(dāng)?shù)讓拥臄?shù)據(jù)存儲可能會變化的時候,開發(fā)人員可以采用抽象代理的方法來實現(xiàn)數(shù)據(jù)訪問對象;抽象代理的方法會創(chuàng)建一些虛擬的數(shù)據(jù)訪問對象代理和各種類型的實際數(shù)據(jù)訪問對象代理,每種對象對應(yīng)一種持久性存儲介質(zhì)的實現(xiàn),一旦組件得到這些代理,就可以利用來創(chuàng)建需要使用的數(shù)據(jù)訪問對象。

          圖11給出了這種情況的類圖。該類圖表示了一個基礎(chǔ)的數(shù)據(jù)訪問對象代理,它是一個抽象類,被其他一些實際的數(shù)據(jù)訪問對象代理繼承以支持特定的數(shù)據(jù)訪問函數(shù);用戶可以得到一個實際的數(shù)據(jù)訪問對象,并利用它來創(chuàng)建需要的數(shù)據(jù)訪問對象而訪問相關(guān)的數(shù)據(jù),每一個實際的數(shù)據(jù)訪問對象都負(fù)責(zé)建立對于數(shù)據(jù)源的連接,并得到和管理所支持的業(yè)務(wù)數(shù)據(jù)。

          圖11 抽象代理使用DAO

          下圖12是這種情況下的序列圖。

          圖12抽象代理使用DAO序列圖

          這種設(shè)計模式的優(yōu)勢:

          • 透明性好。業(yè)務(wù)對象可以在不知道數(shù)據(jù)源實現(xiàn)細(xì)節(jié)的情況下訪問數(shù)據(jù)。由于一切數(shù)據(jù)訪問細(xì)節(jié)被數(shù)據(jù)訪問對象所隱藏,所以這種訪問過程是透明的。
          • 可移植性好。在應(yīng)用系統(tǒng)中添加數(shù)據(jù)訪問對象,可以使得前者能夠很方便地移植到另外一種數(shù)據(jù)庫實現(xiàn)上。業(yè)務(wù)對象與數(shù)據(jù)實現(xiàn)是隔離的,所以在移植過程中,僅僅對數(shù)據(jù)訪問對象進行一些變化即可。
          • 減少業(yè)務(wù)對象的代碼復(fù)雜度。由于數(shù)據(jù)訪問對象可以管理所有的數(shù)據(jù)訪問復(fù)雜細(xì)節(jié),這也就簡化了業(yè)務(wù)模塊和其他數(shù)據(jù)客戶的代碼。同時也提高了應(yīng)用系統(tǒng)的整體可讀性和開發(fā)率。
          • 集中處理所有數(shù)據(jù)訪問。由于所有的數(shù)據(jù)訪問操作都移交給數(shù)據(jù)訪問對象,這樣應(yīng)用系統(tǒng)其他部分就與數(shù)據(jù)訪問實現(xiàn)隔離開來,而全部相關(guān)操作都與數(shù)據(jù)訪問對象集中處理,這樣也使得相關(guān)操作更加容易被維護和管理。

          這種設(shè)計模式的缺陷:

          • 對于容器管理的持久性不能利用。如果EJB容器采取容器管理的方式,那么所有對于持久性數(shù)據(jù)存儲的管理都由容器負(fù)責(zé)。這樣的話應(yīng)用系統(tǒng)就無需實現(xiàn)數(shù)據(jù)訪問對象了,因為應(yīng)用服務(wù)將透明地提供這一功能。
          • 添加了額外的層面。數(shù)據(jù)訪問對象在數(shù)據(jù)用戶和數(shù)據(jù)源之間添加了一個層面,也就增加了一些額外的設(shè)計和實現(xiàn)的負(fù)擔(dān)。當(dāng)然,我們認(rèn)為它是物有所值的。

          總之,在開發(fā)人員選擇不同模式的時候,應(yīng)該注意,一定的模式對應(yīng)于一定的應(yīng)用層次。比如說,與視圖和顯示相關(guān)的模式就是在Web層應(yīng)用的。而一些與業(yè)務(wù)邏輯控制相關(guān)的模式則是與EJB層次相關(guān)的。另外一些關(guān)于讀取數(shù)據(jù)和分派操作的模式則適用于不同的層次之間。

          7、值對象或傳輸對象

          值對象(value object)模式通過減少分布式通信的消息而促進數(shù)據(jù)的交換,通常這里所指的通信是在Web層和EJB層之間。在一個遠(yuǎn)程調(diào)用中,一個單一值對象可以被用來取出一系列相關(guān)數(shù)據(jù)并提供給客戶。

          這種設(shè)計模式的出現(xiàn)是基于客戶需要與ejb大量地交換數(shù)據(jù)的情況。具體來說,在J2EE平臺中,應(yīng)用系統(tǒng)通常將服務(wù)器端的程序組件實現(xiàn)為會話bean和實體bean,而這些組件的部分方法則需要將數(shù)據(jù)返回給客戶;這種情況下,通常一個用戶會重復(fù)調(diào)用相關(guān)方法多次,直到它得到相關(guān)信息,應(yīng)該注意的是,多數(shù)情況這些方法調(diào)用的目的都是為了取得單一的信息,例如用戶名或者用戶地址等。

          顯而易見,在J2EE平臺上,這種調(diào)用基本上都是來自遠(yuǎn)程的。也就是說,用戶多次調(diào)用相應(yīng)的方法會給Web帶來極大的負(fù)擔(dān),即使用戶和EJB容器加載相同的JVM、OS和計算機上運行EJB程序,由于方法調(diào)用被缺省地認(rèn)為是遠(yuǎn)程任務(wù),所以這種問題依然存在。

          由于以上所提到的問題,在遠(yuǎn)程方法的調(diào)用次數(shù)增加的時候,相關(guān)的應(yīng)用程序性能將會有很大的下降,因此利用多次方法調(diào)用而取得單一的信息是非常低效的;在這種情況,J2EE的研究人員建議使用傳輸對象來包含所有的程序數(shù)據(jù),即每次方法調(diào)用可以發(fā)送和接收這個傳輸對象;當(dāng)用戶向EJB發(fā)出對于程序數(shù)據(jù)的請求時,EJB會創(chuàng)建這個傳輸對象,將它的各個域賦以相關(guān)的數(shù)值,并將整個對象傳送給用戶。

          當(dāng)EJB使用傳輸對象的時候,用戶可以通過僅僅一次方法調(diào)用來取得整個對象,而不是使用多次方法調(diào)用以得到對象中每個域的數(shù)值;由于傳輸對象是通過值傳遞而交送給用戶的,所以所有對于該傳輸對象的調(diào)用或取值都是本地調(diào)用,而不是遠(yuǎn)程方法調(diào)用。不過需要注意的是,這個傳輸對象必須具有對應(yīng)于每個屬性的訪問方法,或者將所有屬性都設(shè)為公共的。   

          類圖13表示了傳輸對象模式的體系結(jié)構(gòu)。

          圖13 傳輸對象類圖

          在圖13中,傳輸對象首先在EJB中創(chuàng)建,然后返回給遠(yuǎn)程客戶;當(dāng)然,傳輸對象也可以根據(jù)需要融合其他的設(shè)計模式。

          圖14顯示了傳輸對象模式中的參與模塊和它們之間的交互。

          圖14 傳輸對象序列圖

          下面我們說明一下傳輸對象模式的各個參與模塊:

          (1)客戶(Client)??蛻舸砹薊JB所提供服務(wù)的使用者,通常是運行于用戶終端的應(yīng)用程序。

          (2)業(yè)務(wù)對象。業(yè)務(wù)對象表示在一個模式中由會話bean、實體bean或數(shù)據(jù)訪問對象(Data Access Object)實現(xiàn)的角色。業(yè)務(wù)對象通常負(fù)責(zé)創(chuàng)建傳輸對象,并根據(jù)請求將其傳送到相關(guān)的用戶;業(yè)務(wù)對象也可以從用戶中取得一個傳輸對象格式的數(shù)據(jù),并應(yīng)用這些數(shù)據(jù)來執(zhí)行一些更新。

          (3)傳輸對象。傳輸對象是一個可序列化的Java對象。在這個對象的類中,通常會有一個包含所有域的構(gòu)造函數(shù),用來創(chuàng)建這個傳輸對象。

          這個傳輸對象中的成員變量基本都被定義為公共,從而無需為它們提供相關(guān)的訪問方法。當(dāng)然如果存在一定安全的需要,相關(guān)的成員變量也可以設(shè)為保護或私有,并且給定各自的訪問方法。由此可見,傳輸對象的設(shè)計是隨著應(yīng)用系統(tǒng)的需要不同而改變的,是否將對象中的成員變量設(shè)為公共,或提供一定的訪問方法,將是一個很重要的設(shè)計問題。

          通常在實現(xiàn)這個模式時,最多采取的是可更新的傳輸對象策略和多傳輸對象策略。    在可更新的傳輸對象策略中,傳輸對象不僅可以從服務(wù)于用戶的業(yè)務(wù)對象中取得相關(guān)信息和數(shù)據(jù),還可以從業(yè)務(wù)對象中得到用戶對于數(shù)據(jù)所需要進行的改變。

          圖15以類圖表的形式表明了業(yè)務(wù)對象和傳輸對象之間的關(guān)系。

          圖15 可更新傳輸對象類圖

          業(yè)務(wù)對象創(chuàng)建了傳輸對象。而用戶通過訪問業(yè)務(wù)對象,既得到了所需的信息,也對相關(guān)數(shù)據(jù)做出了一定的修改;為了能夠使得用戶可以修改業(yè)務(wù)對象各個域的取值,這個對象必須提供一定的變值方法,而出于對Web負(fù)擔(dān)的考慮,業(yè)務(wù)對象所提供的方法最好以傳輸對象為參數(shù)。相應(yīng)地,這些方法可以去調(diào)用傳輸對象所提供的方法,來設(shè)置傳輸對象的各個成員變量的取值;同時在傳輸對象的方法中,我們也可以植入數(shù)據(jù)驗證和完整性檢查的邏輯,這樣在用戶從業(yè)務(wù)對象的方法得到傳輸對象時,可以直接調(diào)用傳輸對象的成員方法進行本地數(shù)據(jù)訪問,當(dāng)然這種本地數(shù)據(jù)訪問不會影響到業(yè)務(wù)對象。

          當(dāng)用戶調(diào)用業(yè)務(wù)對象的變值方法時,該方法會將用戶端的傳輸對象序列化,再將它發(fā)送給業(yè)務(wù)對象;業(yè)務(wù)對象接收到更新的傳輸對象,便將這些更新寫回到自己的對象拷貝中去;    這里需要說明的是,上面提到的寫回只是涉及到被更新的變量,而不是全部變量的寫回,因此我們需要在傳輸對象中另設(shè)置一個變量,來指定哪些成員變量被用戶更新過,這也就使得這種模式的設(shè)計相對復(fù)雜,開發(fā)人員需要考慮同步化和版本控制的問題。

          圖16顯示了這個更新過程的序列圖。

          圖16 可更新傳輸對象序列圖

          多傳輸對象的方法是指一個單一的業(yè)務(wù)對象可以根據(jù)用戶請求制造多個不同的傳輸對象。也就是說,業(yè)務(wù)對象和它所創(chuàng)建的傳輸對象保持一對多的關(guān)系。類圖17表示了這種實現(xiàn)方法的各個參與模塊以及它們之間的調(diào)用關(guān)系。

          圖17 多傳輸對象類圖

          當(dāng)一個用戶需要A類型的傳輸對象時,他會激活相關(guān)EJB的getDataA()方法來取得傳輸對象A;當(dāng)他需要B類型的傳輸對象時,他會激活getDataB()方法來獲取傳輸對象B;依此類推。序列圖18表示了這一過程。

          圖18 多傳輸對象序列圖

          使用這種設(shè)計模式,應(yīng)用系統(tǒng)的實體bean及其遠(yuǎn)程接口會變得十分簡單。實體bean中無需再為每一個成員變量都實現(xiàn)一個set()和get()方法,并在遠(yuǎn)程接口中實現(xiàn)相應(yīng)的定義。用戶無需再進行多次的方法調(diào)用來取得信息和數(shù)據(jù),所需要的只是一次方法調(diào)用以獲得整個傳輸對象。當(dāng)然這里需要考慮Web負(fù)擔(dān)和大量數(shù)據(jù)一次傳輸?shù)臋?quán)衡。開發(fā)人員可以根據(jù)不同的需要來選擇不同的實現(xiàn)方法。

          如上所述,用戶和實體bean之間可以通過在一次方法調(diào)用中使用傳輸對象而交換所有的數(shù)據(jù),也就是說傳輸對象作為數(shù)據(jù)載體工作,并減少了遠(yuǎn)程的方法調(diào)用,從而大大減輕了Web負(fù)擔(dān)。通過使用傳輸對象的方法,我們也將有可能減少實體bean和其傳輸對象間的代碼重復(fù)。不過在使用可更新的傳輸對象方法時,用戶可以修改其本地的傳輸對象,之后再將其傳送回業(yè)務(wù)對象中,后者將所需的更新整合到自己一端;但是這樣一來,就會存在一個版本控制的問題,不同的客戶可能在同時修改相同類型的傳輸對象,而如果相關(guān)的業(yè)務(wù)對象沒有發(fā)現(xiàn)這一點的話,可能就會造成一些用戶的數(shù)據(jù)沒有得到及時更新,而另外一些用戶的數(shù)據(jù)又被覆蓋的情況;在系統(tǒng)設(shè)計中必須考慮這個問題。

          8、截取過濾器

          截取過濾器(intercepting filter)主要用于對于用戶請求的之前處理和之后處理,也就是說它對于客戶的請求使用了額外的操作。比如說,servlet可以處理一個網(wǎng)站的所有客戶請求并提供一個核心的認(rèn)證機制。

          這種模式主要工作于表示層,負(fù)責(zé)處理不同類型的請求,同時也需要進行多種不同的處理。在這些請求中,有一些請求會直接傳送給后端模塊處理,而另外一些請求則先會在過濾器里解釋或補充內(nèi)容,之后才能傳送給后端模塊。這種模式的提出主要是由于一個客戶的Web訪問和系統(tǒng)響應(yīng)都需要一定的預(yù)處理和后處理,例如用戶身份、用戶環(huán)境信息、用戶請求的合法性等。通常這些處理的結(jié)果都會決定用戶的請求是否能夠進行,或是系統(tǒng)的響應(yīng)應(yīng)該用什么格式來表示。

          對于這種預(yù)處理和后處理問題,傳統(tǒng)上,開發(fā)人員會設(shè)計一系列額外的檢測程序模塊,也就是一整套if/else語句,并且指定如果其中任何一個檢測失敗,所有的處理工作都會退出。顯然,這種方法是存在很大弊端的,即代碼的可讀性、可維護性都會被大大降低,同時將檢測工作融于一般的程序模塊,使得整個程序的模塊性難以保證。

          解決這種問題的關(guān)鍵在于,設(shè)計一種簡單的技術(shù),以能夠添加或移除額外處理的模塊,而這些模塊通常都能夠完成一定的檢測和過濾功能。根據(jù)以上的討論,J2EE研究人員提出了設(shè)計模式----截取過濾器作為解決方案,這種模式可以在不影響核心處理模塊的情況下,實現(xiàn)可插入的過濾器來執(zhí)行一般的處理功能。   

          從理論上來說,這種過濾器可以截取客戶請求和系統(tǒng)響應(yīng),并進行相應(yīng)的預(yù)處理和后處理;同時開發(fā)人員也可以隨時根據(jù)需要移除這些過濾器,并不用擔(dān)心會改變?nèi)魏纹渌K。   

          我們這里所說的預(yù)處理和后處理功能,通常是指一些基本的系統(tǒng)服務(wù),如安全、登錄,系統(tǒng)調(diào)試等。執(zhí)行這些功能的過濾器通常是需要與核心模塊分開的,并且由于系統(tǒng)職能或規(guī)則的變化,這些模塊隨時可能被添加或刪除。

          下面提供一些關(guān)于截取過濾器的圖示,以幫助大家更好地理解這種設(shè)計模式,并合理地加以運用。圖19表示了截取過濾器模式的整體結(jié)構(gòu),圖19顯示了截取過濾器中的參與模塊和相互之間的聯(lián)系。

          圖19 截取過濾器模式

          圖20 截取過濾器序列圖

          下面我們分別來說明圖20中的各個模塊:

          (1)過濾管理器(Filter Manager)。過濾管理器負(fù)責(zé)過濾器的主要處理工作,即創(chuàng)建過濾器鏈對象以及相應(yīng)的過濾器組建,并初始化整個處理過程。

          (2)過濾器鏈(Filter Chain)。過濾器鏈?zhǔn)且唤M互不依賴的過濾器有序集合。

          (3)過濾器1,過濾器2,過濾器3(FilterOne,F(xiàn)ilterTwo,F(xiàn)ilterThree)。這些都是提供不同服務(wù)的過濾器,而過濾器鏈則負(fù)責(zé)它們的協(xié)調(diào)工作。

          通過采用這種設(shè)計模式,應(yīng)用系統(tǒng)可以取得更方便的中心控制,這是由于過濾器可以提供處理多種請求的中心模塊,并能根據(jù)后端的處理模塊而解釋和潤色用戶的請求,使得該請求能更好地與處理模塊所提供的功能匹配。另外,過濾器通??梢詫⒉煌N類的服務(wù)聚集在一起,并提供相當(dāng)靈活的服務(wù)組合,應(yīng)用系統(tǒng)可以通過使用截取過濾器提高其重用性,過濾器可以隨時根據(jù)需要從其他程序模塊中插入或移除,并且由于它們通常具有標(biāo)準(zhǔn)的接口,開發(fā)人員可以使用一組類似的過濾器,并在不同的情況下進行全組的重用。

            采用這種設(shè)計模式也會帶來一定的問題,即在過濾器之間共享信息將變得非常困難,這是由于根據(jù)其定義和需求,每個過濾器的設(shè)計和開發(fā)都大相徑庭。因而如果在不同的過濾器之間需要共享信息的話,其代價將是非常昂貴的。

          作者:務(wù)實,多年從事J2EE網(wǎng)站及應(yīng)用系統(tǒng)項目的開發(fā)和應(yīng)用。

          參考資料:

          《J2EE設(shè)計開發(fā)編程指南》Rod Johnson 電子工業(yè)出版社

          《J2EE參考大全》Jim Keogh 電子工業(yè)出版社

          《實用J2EE設(shè)計模式編程指南》Craig A.Berry 電子工業(yè)出版社

          posted on 2007-07-27 16:40 前方的路 閱讀(342) 評論(0)  編輯  收藏 所屬分類: Java技術(shù) 、軟件架構(gòu)
          主站蜘蛛池模板: 璧山县| 山西省| 合山市| 峨边| 杨浦区| 水富县| 来安县| 平邑县| 延安市| 长武县| 社旗县| 鄱阳县| 景宁| 通渭县| 东明县| 巴彦县| 龙陵县| 凉城县| 上林县| 河西区| 南宫市| 休宁县| 林芝县| 普陀区| 博兴县| 留坝县| 论坛| 河间市| 浦东新区| 忻州市| 普安县| 同仁县| 安康市| 五常市| 荣成市| 寿光市| 虞城县| 衡阳市| 五华县| 正安县| 崇左市|