EJB設計模式(第二版)之EJB Command (轉)

gugu99發表於2008-05-14
EJB設計模式(第二版)之EJB Command (轉)[@more@] Command

一個ejb客戶端為了完成一個用例需要商業邏輯。

怎樣讓一個開發者用一個輕量級的態度實現一個用例的
商業邏輯,使客戶端和ejb解耦並且用一個事務和一次
執行用例?

設計ejb時的一個重要的架構決定是把商業邏輯
放到什麼地方?一個用例的商業邏輯是代表你的領域
模型中的合適的方法或跨多個其它entity bean 和/或
session bean執行邏輯(工作流邏輯)。

把商業邏輯放到客戶端(,applet,等等)有嚴重的
負面效果,影響和可維護性,如session facade
所解釋的。問題可以被使用session facade模式
糾正,需要把商業邏輯放到session bean中,session
bean的每個方法對映到一個特定的工作單元,或者
用例。這樣做,客戶端被從端的模型遮蔽
起來,並且在一個事務和一次網路呼叫的round trip中
執行用例。

session facade模式自己是ejb開發的關鍵,不過也有
它自己的缺點。直接從客戶端呼叫session facade會導
致客戶端和伺服器之間的依賴(在一個大型專案和複雜的
客戶端程式碼中),因為對EJB的緊耦合,如Business
Delegate模式所討論的。這些問題能被用 business delegate
解決,增加一個封裝所有對ejb層的存取的物件層。business
delegate能幫助讓客戶端程式碼簡單,使客戶端和伺服器之間的
依賴最小。

然後session facade模式和business delegate模式一起提供了
使客戶端從伺服器端的實現細節解耦並允許在一個網路呼叫
和一個事務中執行用例的格式下寫商業邏輯的最好的實踐。
和通常一樣,有trade-off:
1.更慢的開發過程。因為用例邏輯(經常會變化的)在一個
session bean中執行,任何時候一個用例需要改變(就是,
增加一個引數到一個方法或返回一個額外的屬性),實現
那個用例的session bean方法可能需要修改。改變一個
session bean的過程不是可以忽略不計的----一個改變通常
需要編輯3個不同的(介面,bean class,deployment
descriptor)並且對ejb server的重發布和可能的重起伺服器。
附加的,封裝變化的session bean的在客戶端的business
delegate將也需要修改。

2.大型專案中的勞動分工將更困難。依賴於一個專案中跨
開發者分配工作的策略,session facade是導致不同組或
開發者互相爭鬥的瓶頸,因為它將是隨著專案進展時經常
變化的主題。

3.在一個大型公司中伺服器資源經常被一個小組控制。
對一個有建立了的並且正在工作的釋出的ejb集合的大型
公司,很難讓其他專案的小組對已有的類施加影響和改變。

簡單說,用session facade和business delegate開發會導致
長期的變化->釋出->測試的round-trip,會成為大型專案的
瓶頸。問題的關鍵是商業邏輯放在一個session bean層,
幾乎是重量級的開發。

綜上所述:
 使用Command模式來封裝商業邏輯到輕量級的command
bean,使客戶端從EJB解耦,在一個網路呼叫中執行,作為
EJB層的一個facade。

一個command bean只是一個有get,set和一個execute方法的
普通類,和最初的command模式(四人幫(gof),1995)描述
的一樣。應用到EJB,Command模式為了達到和session facade
和business delegate相同的好處提供了一個輕量級解決方案:
一個隱藏ejb層的物件模型,在一個事物和一次網路呼叫中執
行一個用例,完成使客戶端從ejb解耦的facade。command模式
透過提供本地互動的類達到這一點,不過實際上在一個
ejb伺服器上執行,對客戶端透明。

Command被用來封裝應用中的單獨的工作單元。比如
placeOrder,tranerFunds,等等的用例,將有它的商業/工作流
邏輯封裝在只為那個用例的特定的Command,如圖1.7所示。

和一個command互動的客戶端十分簡單。一旦一個客戶端得到
一個command(建立一個或從一個factory得到,取決於實現),
它只是簡單的對command設定屬性,直到command包含所有需要
執行用例的資料。這時客戶端能呼叫command的execute方法,
然後簡單的執行command上的get直到得到所有command和用例
的結果資料。

當客戶端執行command,有趣的事情在幕後發生。不是本地執行,
command實際輸到一個遠端ejb伺服器並在ejb伺服器的JVM
中執行。然而,所有的在執行用例的過程中被command呼叫的
ejb發生在ejb伺服器上,一個用例能在一個事物中執行。這個
行為的實現機制晚些時候將在這個模式的討論中講解。

使用transfunds例子,一個客戶端將設定用來取錢,存錢,傳輸
量的賬號的ID。呼叫transfunds command的execute後,客戶端
將得到最後賬戶的平衡,如1.8圖所示。

可能Command模式最完善的實現之一是IBM的Command,和sphere
一同出現,是IBM為電子商務的模式的一部分。有很多實現ejb command
模式的方法,不過他們都有3個要素:

1.Command bean。一個有get,set和一個包含需要執行一個用例的商業邏輯
的execute方法的簡單的java bean。command bean是應用程式開發者需要
寫的command模式的唯一部分,下面所解釋的其他是可以跨工程複用的。

2.客戶端邏輯。通常負責執行命令(command)並把它傳送到遠端ejb
伺服器的一個類的框架。這個路由邏輯通常對客戶端不可見,透過呼叫
command的execute方法來觸發。路由邏輯/框架是一個普通的能被跨工程
複用的類的集合。

3.遠端Command server。Command server是簡單的接受命令(commands)
並執行它們的服務。應用到ejb,command server類是一個接受命令(command)
作為引數並本地執行之的stateless session bean。Command server也是
普通的(generic)並且完全跨專案可複用。

客戶端和這3個元件之間的互動如圖1.9所示。在這個例子中,客戶端呼叫
路由邏輯元件上的executeCommand方法。在IBM command框架中,客戶端
只需要呼叫command自己的execute,因為方法呼叫將實際上被command的
超類接收到,它是路由邏輯框架的一部分。

在幕後,CommandExecutor了對一個ejb command目標(因為它是路由
邏輯的一部分,所以沒有在圖1.9中表示出來)的呼叫,它被編碼成知道ejb
並且知道怎樣傳送命令(command)到command server stateless session
bean。透過接受命令(command),command server簡單的呼叫command的
execute方法,command然後繼續它的商業邏輯。

Command模式的好處如下:
1.因為輕量級的開發/分發過程,方便了RAD。
把一個用例寫成Command bean比寫成一個session
bean方法相對更容易和去分發和測試。經常
的變化能在一個普通java類上做,而不是一個
完全的EJB。

2.把商業邏輯從表示邏輯分離。Command透過封裝
command內的商業邏輯來作為伺服器上物件模型
的一個facade,只暴露一個簡單的command介面
讓客戶端使用。這個分離讓客戶端和伺服器分開
的演進。

3.強制用例在一個單獨的round trip中執行。
因為command實際上在EJB伺服器上執行,只需要
一次網路呼叫(和一個事務)來完成一個複雜的
用例。

4.使客戶端從ejb解耦。客戶端是完全的從伺服器的
實現細節解耦的--所有它們能看見的只是command bean,
command bean看上去象是本地類。

5.命令(command)可以本地執行或產生啞(dummy)資料。
空的或虛的命令(command)能在專案開始前被建立,
允許表示層開發者去對於商業邏輯和ejb小組相對獨立的
寫,編譯,和測試他們的程式碼。

很多方面command模式聽起來像個終極的解決方案,綜合了
session facade和business delegate的好處,和一個
輕量級的基礎。然而,好處和通常一樣,被重要的trade-off
所平衡:
1.非常粗粒度的事務控制。因為command只是普通java bean,
沒有自動的標記一個command去在一個特定的事務設定或
isolation level下執行的方法,而你用session bean方法可以。
Command只能在執行它們的Command server的事務設定下執行。
這個的結果是用不同的jndi名字和事務設定(在deployment
descriptor中)來分發多個command server session bean。
路由邏輯元件需要被配置成傳送特定的命令(command)到command
server。就是說,一種方法想傳送只讀command到沒有事務的
session bean,然而命令能在command server下用tx_required
和可序列化的isolation level執行。

2.command是無狀態的。command物件不能任何狀態到執行它的
session bean中。用command模式在ejb層儲存狀態是不可能的。

3.笨拙的錯誤處理。因為command框架是通用的(generic),從
command只有CommandException能被丟擲。這意味著,應用程式
異常,如NoMoneyAccountException,需要被捕獲並用CommandException
封裝。然後客戶端需要為了特定的異常透視到command物件裡面。因為
異常不是顯式的宣稱的,客戶端失去了編譯期檢查異常處理的好處。

4.command在大型專案中會變得無法管理。用成千的command,
大型專案會爆炸的,很多command有重複的商業邏輯的部分,
特別當不同的專案小組使用同樣的後端領域模型。這使得
維護商業邏輯層比起在session bean方法中實現用例的session
facade(很好的分組到數目很小的session bean中)困難得多。
這種類的激增將是大型專案的嚴重問題。

5.Command Server ejb-jar緊密的耦合到command bean和
其它ejb。因為command bean在command server的環境下
執行,為了使command bean反序列化和執行,command bean
類需要和command server session bean一起分發(在相同的
ejb-jar或EAR中)。這意味著只要command bean變化了,command
server session bean EAR或ejb-jar將需要重新分發(因此command
server claoader能讀到所有包含的command的新版本),為了
測試變化,或完全重起(如果你的應用伺服器不支援熱分發)。
還有,command bean需要看見任何在它們的商業邏輯中使用到的
home,remote,local home,或local interface。這需要或者當
ejb被任何它們的command bean存取時command server分發到
相同的EAR,或者存取ejb的interface和command server的ejb-jar
打包到一起。

command模式和session facade模式一起提供了兩個重要的好處:
他們作為一個facade和它們在一個網路round trip中執行。另一個
command模式比session facade模式好的主要優點是把客戶端從
ejb解耦了,用business delegate和session facade一起也可以達
到。因此,開發者怎樣從中選擇呢?把command看作是更便宜(cheaper)
的session bean會有所幫助。它們是輕量級的,更快的先導開發過程,
以後來的差的可維護性作為代價。

相關模式
command(四人幫(gof),1995)
Data Transfer HashMap


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-1004041/,如需轉載,請註明出處,否則將追究法律責任。

相關文章