av一区二区在线观看_亚洲男人的天堂网站_日韩亚洲视频_在线成人免费_欧美日韩精品免费观看视频_久草视

您的位置:首頁技術(shù)文章
文章詳情頁

Session Facade 的規(guī)則和模式

瀏覽:31日期:2024-07-20 18:32:15
內(nèi)容: Kyle Brown Java 執(zhí)行設(shè)計(jì)師,IBM WebSphere Service 2001 年 6 月 在過去幾年中,Enterprise JavaBeans&#8482;(EJB)確實(shí)已經(jīng)開始對 Java&#8482; 對象設(shè)計(jì)產(chǎn)生影響。期間,我們看到的最常使用的 EJB 模式之一是Session Facade 概念。這是一個(gè)讓很多開發(fā)者都受益匪淺的既強(qiáng)大又非常簡單的概念。然而,我也看到,對這一模式的確切含義及其在實(shí)踐中的應(yīng)用,人們?nèi)杂泻芏嗾`解。 為了把這個(gè)問題講得更明白些,我會(huì)在本文中講述 Facade 的一些基本概念以及Session Facade 模式的工作機(jī)制,并探討該模式衍生出來的一些問題。希望能借此澄清一些誤解,并幫助開發(fā)者正確使用這種模式。 什么是Session Facade?您又為什么需要它? 很多地方都有對Session Facade 模式的清楚描述,也就是 [Sun 2001] 和 [Brown 2000]。我不想照抄那里的全部內(nèi)容,而打算把它的理論在此作個(gè)總結(jié):基本的問題是在 EJB 設(shè)計(jì)中,EJB 客戶機(jī)(例如,Servelet、Java 應(yīng)用程序,等等)不可直接訪問 Entity bean。 之所以如此,有以下幾個(gè)原因: 當(dāng)依靠 RMI-IIOP 進(jìn)行跨越網(wǎng)絡(luò)的調(diào)用時(shí)運(yùn)行態(tài)的性能會(huì)受到極大影響。如果客戶機(jī)請求一個(gè)Entity bean 去表示如包含兩項(xiàng)數(shù)據(jù)(比方說帳戶余額和帳戶所有者姓名)的銀行帳戶,則將需要兩個(gè)網(wǎng)絡(luò)調(diào)用。當(dāng)大量屬性使網(wǎng)絡(luò)調(diào)用成倍增加時(shí),很快這些開銷就會(huì)變得非常明顯。[Monson-Haefel] 中所說的批量訪問器(bulk accessors)或許是一種解決方案,所謂批量訪問器,就是Entity bean 上的一些方法,它們創(chuàng)建并返回值對象以表示Entity bean 中的數(shù)據(jù)。它事實(shí)上就是 Java VisualAge&reg; 的 CopyHelper Access Beans 采用的解決方案。但是,它有一個(gè)令人遺憾的缺陷,就是它假設(shè)所有的請求都需要 EJB 中的“所有數(shù)據(jù),結(jié)果為用戶返回了一些不必要的數(shù)據(jù),并導(dǎo)致對更大的值對象進(jìn)行組織和分解時(shí)產(chǎn)生額外開銷。 更重要的是,如果您允許 EJB 客戶機(jī)直接訪問Entity bean,那么就要求客戶機(jī)了解Entity bean 的內(nèi)部方法,而這已經(jīng)超出了客戶機(jī)的應(yīng)知的范圍。例如,操作一個(gè)Entity bean 需要知道所涉及到的該實(shí)體的關(guān)系(關(guān)聯(lián),繼承),這樣就把業(yè)務(wù)模型的所有細(xì)節(jié)不適當(dāng)?shù)乇┞督o了客戶機(jī)。另外,操作多個(gè)Entity bean 會(huì)要求使用客戶端事務(wù) ? 這是另一個(gè)使事情復(fù)雜化的因素,這意味著 EJB 可能要被從客戶機(jī)設(shè)計(jì)中除去,而不是添加上去。 大多數(shù)設(shè)計(jì)師已經(jīng)發(fā)現(xiàn)為了在 EJB 設(shè)計(jì)中避免直接訪問Entity bean 的解決方案都可以在 Gamma 中描述的 Facade 中找到。 Gamma 這樣描述 Facade 模式:“為子系統(tǒng)中的一套接口提供了一個(gè)統(tǒng)一的接口。Facade 定義了一個(gè)更高層次的接口,使子系統(tǒng)更容易使用。1在 EJB 中應(yīng)用這種思想一般意味著您應(yīng)該創(chuàng)建一個(gè)擔(dān)當(dāng) Facade 的Session EJB,然后把構(gòu)成子系統(tǒng)的一套Entity bean “包裝起來。這樣,客戶機(jī)就和Entity bean 實(shí)現(xiàn)的細(xì)節(jié)分離開來了,而且不必自己管理事務(wù)管理的細(xì)節(jié)。 但問題是有很多人到此就打住了。然后他們輕松地往下做,開始把Entity bean 包裝到Session bean 中,而不考慮 Facade 模式所描述的其它內(nèi)容以及 EJB 設(shè)計(jì)中由 Facade 模式衍生出來的問題。這很可能是由于把得到的 Facade 的“二手信息都當(dāng)真,而沒去研究原始模式的緣故。如果我們確實(shí)花了些時(shí)間去理解 Facade 衍生的問題,我們將可以看到很多該模式所固有的其它有益的設(shè)計(jì)可能性。 Facade 模式的要點(diǎn) Gamma 中描述了很多我們應(yīng)該了解的 Facade 模式的要點(diǎn)。前面幾點(diǎn)可在 Facade 模式的“適用性描述部分找到,它描述了在什么情況下您會(huì)需要應(yīng)用該模式。它們是:“當(dāng)您想為復(fù)雜的子系統(tǒng)提供一個(gè)簡單接口時(shí)……請使用 Facade 模式和“當(dāng)您想把子系統(tǒng)分層時(shí)……請使用 Facade 模式。使用 Facade 為每一層子系統(tǒng)定義一個(gè)入口點(diǎn)。2 從對 Facade 模式的討論中,我們可以提煉出兩個(gè)觀點(diǎn)。第一點(diǎn)是 Facade 應(yīng)該提供子系統(tǒng)的一個(gè)抽象視圖,而不是簡單地把整個(gè)子系統(tǒng)本身的 API 直接包裝起來。不幸的是,我在實(shí)際中多次看到開發(fā)者創(chuàng)建的Session bean 把Entity bean home 和Entity bean 對象的全部方法直接包裝起來,而不提供任何額外的抽象,這是對該模式最可惡的濫用情況之一。請記住,這種思想是想降低整個(gè)系統(tǒng)的復(fù)雜性,而不是把復(fù)雜性轉(zhuǎn)移到另一個(gè)對象上。 第二點(diǎn),也是更微妙的一點(diǎn),與分層有關(guān)。這個(gè)觀點(diǎn)認(rèn)為您可以用多重 Facade 來隱藏下層子系統(tǒng)的細(xì)節(jié)。因此,在這里您可以這樣設(shè)想,Session Facade 應(yīng)該在其它 Facade 之上,位于最上層,是對底層業(yè)務(wù)邏輯細(xì)節(jié)的進(jìn)一步抽象。這一點(diǎn)很關(guān)鍵。當(dāng)您看完下面兩條(分別出自 Gamma 中論述 Facade 模式的“協(xié)作和“相關(guān)模式部分)敘述后,就會(huì)更加清楚這一點(diǎn): “客戶機(jī)通過把請求發(fā)送給 Facade,再由 Facade 把請求轉(zhuǎn)發(fā)給適當(dāng)?shù)淖酉到y(tǒng)對象來與子系統(tǒng)通信。3 “facade 只是對通往子系統(tǒng)對象的接口進(jìn)行抽象以使它們更易于使用;它不定義新功能。4 我把這幾點(diǎn)總結(jié)如下:Facade 不做系統(tǒng)的實(shí)際工作;而是委托其他對象輪流做這個(gè)工作。由此推理出您必須正確地放置這些對象,以便使該模式能按照您所期望的運(yùn)行。 這一點(diǎn)是本模式的兩種流行表達(dá) [Sun 2000] 和 [Sun 2001] 之間的主要不同之處。第一個(gè)版本,即 [Sun 2000],是 J2EE 規(guī)劃的一部分,它把這種模式稱為“Session Entity Facade。它意在表明“為一堆企業(yè) beans 提供單一的接口。它描述了這樣一種模式,即所有的數(shù)據(jù)存取都通過Entity bean 來完成,Session bean 則為這些Entity bean 提供接口?,F(xiàn)在的問題是 [Sun 2000] 不一定非要以 EJB 為中心。它根本不涉及其它對象類型,并且假設(shè)系統(tǒng)中只有 EJB 一類對象。根據(jù)我的經(jīng)驗(yàn),我認(rèn)為這會(huì)導(dǎo)致根本不能在工程間重用的臃腫的Session對象,而且,在同一個(gè)工程內(nèi),當(dāng)需求有一點(diǎn)不同時(shí)就會(huì)出現(xiàn)問題。 現(xiàn)在,[Sun 2001] 則更通用,也沒有上述問題的困擾。它簡單地把這種模式稱為“Session Facade。它的解決方案規(guī)定您應(yīng)該“把Session bean 當(dāng)作 facade 來用,以封裝參與工作流的業(yè)務(wù)對象之間的交互操作的復(fù)雜性。它根本不限制您的業(yè)務(wù)對象應(yīng)該為 EJB,因此是一個(gè)更加靈活的方法。 Session Facade 的重要規(guī)則 那么我們該如何應(yīng)用這些關(guān)于針對會(huì)話的 Facade 的規(guī)則呢?這對我們的 EJB 設(shè)計(jì)又意味著什么呢?我在設(shè)計(jì)Session Facade 時(shí)遵循三條基本原則: 它們自己不做實(shí)際工作;它們委派其它對象做實(shí)際工作。這意味著Session facade 中的每個(gè)方法都應(yīng)該很小(異常處理邏輯不計(jì)算在內(nèi),代碼應(yīng)為五行或更少)。 它們提供簡單的接口。這意味著 facade 方法的數(shù)量應(yīng)相對較少(每個(gè)Session bean 中僅有約 24 個(gè))。 它們是底層系統(tǒng)的客戶端接口。它們應(yīng)該把特定于子系統(tǒng)的信息封裝起來,并且不應(yīng)該在不必要的情況下公開它。 那么它的工作機(jī)制呢?您還能代理別的哪些類型的對象呢?這又會(huì)給您的設(shè)計(jì)帶來什么好處呢?在我的一篇早期論文和 [Brown 2001] 這本書中,我已論述了其中一些問題,在那里可以找到一些詳細(xì)信息。但,總的來說,在我的多數(shù) EJB 設(shè)計(jì)中我通常會(huì)找到以下四類對象: 值對象是包含了客戶機(jī)所請求的數(shù)據(jù)的、可序列化的 Java bean。它包含Entity bean 和其他數(shù)據(jù)源所包含的數(shù)據(jù)的一個(gè)子集。它是Session EJB 方法的返回類型。[EJB 2.0] 和 [Sun 2001] 都描述了值對象和值對象的用途。請注意 [Fowler 2001] 稱其為“數(shù)據(jù)傳輸對象( Data Transfer Objects ),[Brown 1999] 也使用這個(gè)名稱。我個(gè)人覺得數(shù)據(jù)傳輸對象是描述性更好的術(shù)語,但不幸的是,Sun 的術(shù)語似乎更通用。 對象制造廠 (Factory) [Brown 1999] [Brown 2000] 負(fù)責(zé)構(gòu)建值對象。它能完成辨別不同的數(shù)據(jù)源、創(chuàng)建值對象的實(shí)例、填充值對象的實(shí)例等等工作。每個(gè) factory 類 都可以從多個(gè)數(shù)據(jù)源中檢索數(shù)據(jù)或更新其中的數(shù)據(jù)。在您的對象模型中,每個(gè)“根對象都應(yīng)該有一個(gè) factory 類。(根對象是那些“包含其它對象的對象。)從某種意義上說,對象 Factory 類在 JDBC 或持久的 Entity bean 子系統(tǒng)上擔(dān)當(dāng) Facade,實(shí)現(xiàn) Gamma 中提到的分層原則。 Entity EJB 應(yīng)該是標(biāo)準(zhǔn)的、企業(yè)全局范圍內(nèi)可用的“數(shù)據(jù)源。Entity bean 不應(yīng)包含特定于應(yīng)用程序的域邏輯,也不應(yīng)限制為只能在單一應(yīng)用程序內(nèi)工作。請注意Entity bean 是可選的,它不是這種體系結(jié)構(gòu)中必需的部分;Factory 可能像 JMS 隊(duì)列或 JDBC 連接那樣簡單地直接從數(shù)據(jù)源獲取數(shù)據(jù)。 Action 對象是Session bean 可能調(diào)用的唯一對商業(yè)業(yè)務(wù)進(jìn)行處理的對象。Action 對象只處理與簡單的創(chuàng)建、讀取、更新或刪除數(shù)據(jù)無關(guān)的商業(yè)流程。和對象 Factory 一樣,Action 對象也充當(dāng)內(nèi)層 Facade。 一個(gè) EJB 對象示例 描述類似這樣的模式遇到的一個(gè)問題是,能夠使用這種模式的示例都太大,以至于無法包含在模式自身的描述中。盡管如此,我還是要嘗試舉出如下示例(它顯然很簡單)來說明一下這些對象看起來是什么樣子。 假設(shè)我們正在為銀行構(gòu)建一個(gè) ATM 系統(tǒng)。這是最老掉牙的 OO 設(shè)計(jì)問題之一,當(dāng)然其它很多書籍和論文已經(jīng)討論過它,但它確實(shí)有足夠符合我們要求的有趣特點(diǎn)。通過分析,我們發(fā)現(xiàn)了兩種 EJB。 從 ATM 到銀行的連接表示為Session bean。該 bean 上有一些方法負(fù)責(zé)處理您通過 ATM 可以完成的交易 ? 存款、取款以及帳戶間的資金轉(zhuǎn)移。 帳戶表示為Entity bean(我們的示例采用 CMP,但它在我們的示例中實(shí)際上并沒什么影響)表示。它有返回帳戶余額、對帳戶進(jìn)行借貸處理的方法。 ATM Session bean 的遠(yuǎn)程接口如下: package com.ibm.bankexample.ejbs; import com.ibm.bankexample.domain.*; /** * This is the Enterprise Java Bean Remote Interface * for the ATM example. */ public interface ATM extends javax.ejb.EJBObject { void deposit(java.lang.String accountNumber, double amount) throws java.rmi.RemoteException, com.ibm.bankexample.domain.FactoryException; java.util.Vector getAccounts(java.lang.String userid) throws java.rmi.RemoteException, com.ibm.bankexample.domain.FactoryException; void transfer(java.lang.String fromAccount, java.lang.String toAccount, double amount) throws java.rmi.RemoteException, com.ibm.bankexample.domain.InsufficientFundsException, com.ibm.bankexample.domain.FactoryException; void withdraw(java.lang.String accountNumber, double amount) throws java.rmi.RemoteException, com.ibm.bankexample.domain.InsufficientFundsException, com.ibm.bankexample.domain.FactoryException; } 同樣地,帳戶 EJB 的遠(yuǎn)程接口如下: package com.ibm.bankexample.ejbs; /** * This is the Enterprise Java Bean Remote Interface * for the Account Entity EJB. */ public interface Account extends javax.ejb.EJBObject { void deposit(double amount) throws java.rmi.RemoteException; java.lang.String getAccountNumber() throws java.rmi.RemoteException; double getBalance() throws java.rmi.RemoteException; java.lang.String getUserid() throws java.rmi.RemoteException; void setBalance(double newValue) throws java.rmi.RemoteException; void setUserid(java.lang.String newUserid) throws java.rmi.RemoteException; void withdraw(double amount) throws java.rmi.RemoteException; } 現(xiàn)在,我們還發(fā)現(xiàn)有另外兩種對象類型對我們的系統(tǒng)是有用的。第一種是描述顯示在 ATM 機(jī)上的帳戶信息的值對象。這個(gè)類看起來如下所示: public class AccountValue implements java.io.Serializable { private java.lang.String accountNumber; private double balance; } 當(dāng)然,AccountValue 類也有作為屬性的 getter 和 setter 的方法,但我們暫時(shí)不考慮它們。 現(xiàn)在,我們基本上有了足夠的信息來理解 ATM EJB 的 getAccounts() 方法的實(shí)現(xiàn)。這個(gè)方法的實(shí)現(xiàn)如下: public java.util.Vector getAccounts(String userid) throws FactoryException { AccountFactory fact = new AccountFactory(); Vector result = fact.getAccounts(userid); return result; } 這個(gè)方法展示了Session Facade EJB 的方法的標(biāo)準(zhǔn)模式。它找到合適的幫助對象(Action 或 Factory,在本例中是 Factory),調(diào)用幫助對象上的業(yè)務(wù)方法,然后返回結(jié)果。 如這個(gè)方法所指出的,我們需要一個(gè) AccountFactory 類來從 Accounts 構(gòu)建 AccountValues。這個(gè)類的類定義如下: public class AccountFactory { private static AccountHome accountHome = null; } AccountFactory 的 getAccounts(userid) 方法的實(shí)現(xiàn)如下: public java.util.Vector getAccounts(String userid) throws FactoryException { try { Vector vect = new Vector(); AccountHome home = getAccountHome(); Enumeration accountRefs = home.findByUserid(userid); while (accountRefs.hasMoreElements()) { Account acc = (Account) accountRefs.nextElement(); AccountValue valueObject = new AccountValue(); valueObject.setAccountNumber( acc.getAccountNumber()); valueObject.setBalance(acc.getBalance()); vect.addElement(valueObject); } return vect; } catch (Exception e) { throw new FactoryException( 'Cannot generate accounts due to wrapped exception ' + e); } } 這個(gè)方法使用一個(gè)高速緩存的 AccountHome 實(shí)例,它是從以下方法中獲取的: private AccountHome getAccountHome() { if (accountHome == null) { try { java.lang.Object homeObject = getInitialContext().lookup( 'com/ibm/bankexample/ejbs/Account'); accountHome = (AccountHome) javax.rmi.PortableRemoteObject.narrow( (org.omg.CORBA.Object) homeObject, AccountHome.class); } catch (Exception e) { // Error getting the home interface System.out.println( 'Exception ' + e + ' in createTimeSheetHome()'); } } return accountHome; } 正如 [Brown 2001] 和 [Gunther 2000] 所描述的那樣,在 WebSphere&reg; 中,高速緩存 EJB home 是一個(gè)極好的習(xí)慣,因?yàn)楂@取 JNDI InitialContext 和從 InitialContext 獲取 EJB Home 需要一段時(shí)間。 既然您已經(jīng)看到了Session、Entity和 Factory 如何組合在一起,那我們就來看一個(gè) Action 類的示例。在本例中,我們有一個(gè)處理從一個(gè)帳戶到另一個(gè)帳戶的資金轉(zhuǎn)移的 Transfer 對象。Transfer 由 ATM EJB 中的 transfer() 方法的實(shí)現(xiàn)中創(chuàng)建,該方法的實(shí)現(xiàn)如下: public void transfer(String fromAccount, String toAccount, double amount) throws InsufficientFundsException, FactoryException { Transfer trans = new Transfer(); trans.transfer(fromAccount, toAccount, amount); } 請?jiān)俅巫⒁馔瑯拥牧鞒獭2贿^,這個(gè)方法不必從 Action 對象返回值。Transfer 類的定義如下: public class Transfer { private static AccountHome accountHome; } transfer() 方法的實(shí)現(xiàn)如下: public void transfer(String fromAccount, String toAccount, double amount) throws InsufficientFundsException, FactoryException { try { Account from = getAccountHome().findByPrimaryKey( new AccountKey(fromAccount)); Account to = getAccountHome().findByPrimaryKey( new AccountKey(toAccount)); if (from.getBalance() < amount) throw new InsufficientFundsException(); to.deposit(amount); from.withdraw(amount); } catch (Exception e) { throw new FactoryException( 'cannot perform transfer. Nested exception is ' + e); } } 您已經(jīng)看到,Transfer 對象中的 transfer() 方法處理以下細(xì)節(jié):定位兩個(gè) Account 實(shí)體,確保“From帳戶有足夠的余額,把轉(zhuǎn)移金額存入“To帳戶,從“From帳戶中提出轉(zhuǎn)移金額。同樣地,您可以看到 Action 對象的其它方法可以實(shí)現(xiàn)您系統(tǒng)中的其它業(yè)務(wù)規(guī)則。 使用 EJB 對象的原因 那么為什么我們需要這第二層對象呢?難道我們從 CORBA 和 RMI 轉(zhuǎn)到 Enterprise JavaBean 就使事情更簡單了嗎?為什么不把所有的邏輯都放到 EJB 中呢?這有幾個(gè)原因。第一個(gè)也是最重要的原因是這是一個(gè)分層應(yīng)用程序。在單個(gè)對象中放置太多工作從來不是一個(gè)好主意。如果您用這種方式來布置由 EJB 調(diào)用的對象,可以帶來以下好處: 把工作放在一個(gè)會(huì)話層上的一套對象中,使我們可以更容易獨(dú)立地測試它們,或許甚至可以在 J2EE 應(yīng)用服務(wù)器環(huán)境之外對它進(jìn)行測試。 不同的多個(gè)Session Facade 對象可以使用同一層上的對象,而不必?fù)?dān)心事務(wù)語義不正確,也沒有跨Session bean 調(diào)用可能帶來的網(wǎng)絡(luò)和數(shù)據(jù)組織/數(shù)據(jù)分解開銷。 第二層對象允許您對那些對象實(shí)現(xiàn)多樣化(通過使用 Gamma 中介紹的 Stragtegy 模式),這樣便可以利用應(yīng)用服務(wù)器的特有功能,同時(shí)仍然保持整個(gè)設(shè)計(jì)在應(yīng)用服務(wù)器之間的可移植性。例如,[Brown 2000a] 描述了一些特別的高速緩存策略,用于提高那些能在 WebSphere Application Server(高級版)下工作、卻不能在 IBM CICS EJB 支持下工作的 EJB 的性能。通過為同一個(gè) Factory 類或 Action 類提供兩個(gè)實(shí)現(xiàn),您便可以保持整個(gè)設(shè)計(jì)的可移植性,同時(shí)也最大程度地利用各個(gè)服務(wù)器的特有功能。 在您不需要 JTA 事務(wù)的情況下(例如,您只對單一數(shù)據(jù)源進(jìn)行操作),這個(gè)模式允許您選擇部署和構(gòu)建帶或不帶 EJB 的應(yīng)用程序。例如,在一些簡單查詢中,為避免 EJB 調(diào)用的開銷,您可以直接從 servlet 調(diào)用 Factory,這能顯著提高效率。 同時(shí),通過回顧幾個(gè)工程,我們發(fā)現(xiàn)重用只在少數(shù)情況下會(huì)出現(xiàn)在會(huì)話層上。這是因?yàn)?,每個(gè)會(huì)話都有針對一個(gè)特定應(yīng)用程序的一個(gè)事務(wù)設(shè)置與方法的特定組合。有了第二層對象則使您可以在內(nèi)層級別上進(jìn)行重用,我們在很多工程中都看到過這種重用,包括在企業(yè)的一個(gè)工程內(nèi)(在不同的Session bean 之間)和多個(gè)工程之間。 我們已經(jīng)看到,如果采用這種策略,那么您的設(shè)計(jì)經(jīng)??梢园褵o狀態(tài)Session bean 當(dāng)作 Facade 對象使用。由于對某個(gè)用戶而言,每個(gè)無狀態(tài)Session bean 都不是唯一的,這就使您能夠得到無狀態(tài) bean 所提供的另外的可擴(kuò)展性。 既然我們已經(jīng)知道了 facde 背后對象的類型,我們就可以開始看看 facade 能對外提供哪些類型的方法了。我們看到 Facade 方法通常屬于以下幾種類型: Collector 方法通常以“get開頭,返回一個(gè)對象或一個(gè)對象集合(在 EJB 1.0 中是 Emulation,在 EJB 1.1 和 2.0 中則是一個(gè) Java Collection)。如 [Brown 2000] 所述,collector 方法在 Factory 對象中實(shí)現(xiàn)。 Updater 方法根據(jù)作為參數(shù)傳入的值對象所掌握的信息來定位并更新一個(gè)Entity bean 或一個(gè)Entity bean 集。方法名稱常常以“update或“set開頭。updater 方法的實(shí)現(xiàn)可以像 [Brown 2000] 所說的那樣放在 factory 中,或者在一個(gè)單獨(dú)的類中。 Action 方法(例如 transfer(String fromAcctNum, String toAcctNum, BigDecimal amount))的實(shí)現(xiàn)放在 Action 對象中。 Session Facade 的創(chuàng)建規(guī)則 既然您看到了Session Facade 接口的樣子,在Session Facade 背后的又有哪些對象,那么下一個(gè)問題就是“我該有多少Session Facade 呢?您不應(yīng)擁有太多的Session Facade,否則,就喪失了 Facade 模式帶來的好處。但是,若整個(gè)應(yīng)用程序?qū)?yīng)一個(gè)Session Facade 它可能會(huì)成為一個(gè)“巨大的對象5并導(dǎo)致它自身的一些問題。這里是設(shè)計(jì)Session Facade 的一些規(guī)則,使您能適當(dāng)?shù)兀ú贿^多或過少)使用它。 從您的應(yīng)用程序中找出功能子系統(tǒng)。例如,名為定單管理、帳單管理和運(yùn)輸管理的子系統(tǒng)就是一個(gè)應(yīng)用程序中可能有的三個(gè) Facade 對象。 回到您的用例(Use-case)和相關(guān)的用例組。一組相關(guān)的用例 (例如購買股票、出售股票和獲取報(bào)價(jià))可以形成一個(gè)內(nèi)聚子系統(tǒng),例如“股票交易。這個(gè)內(nèi)聚子系統(tǒng)就可能要共享很多內(nèi)層對象,并且是使用Session Facade 的最佳候選。[Sun 2001] 更深入地討論了這個(gè)問題。 千萬不要把所有的單個(gè)用例都做到Session Facade 中。這將導(dǎo)致系統(tǒng)分布截面過大。這種情況下,客戶機(jī)將不得不管理非常多的 EJB 引用和 Home。 完成初步工作后,看一下您的設(shè)計(jì)中第二層對象之間的關(guān)系。如果您看到有值對象、Factory 和 Action 的不相交組,那就根據(jù)實(shí)際分組法把 Facade 分成兩個(gè)或更多 facade。 另一種會(huì)話模式 既然您已深信應(yīng)該使用無狀態(tài)的Session Facade 來包裝數(shù)據(jù)源,也應(yīng)該在這些 facade 的實(shí)現(xiàn)中進(jìn)行嚴(yán)格的分層,您可能會(huì)想知道特定于用戶的應(yīng)用程序狀態(tài)(如果有的話)將被保存在什么地方。根據(jù)我所主張的把Session facade 設(shè)計(jì)成能處理多用例請求,您可能還會(huì)想知道用例在哪里實(shí)際實(shí)現(xiàn)。 為了理解如何應(yīng)用它,我們采用出自 [Jacobson 1999] 的 Control 對象的如下定義:“Control 類代表協(xié)調(diào)、順序事務(wù)以及對其它對象的控制,常用于封裝與特定用例相關(guān)的控制。 這個(gè)解決方案的目標(biāo)是實(shí)現(xiàn)專門的、與一個(gè)單一的用例一一對應(yīng)的“用例控制器對象。每個(gè)用例控制器都將維護(hù)一些特定于用戶的狀態(tài),這些狀態(tài)與判斷一個(gè)用戶在此用例中位于哪里所必需的信息(例如,它們已經(jīng)執(zhí)行了多少)相對應(yīng),也與用戶輸入的、對執(zhí)行用例的下一步來說必需的信息相對應(yīng)。這樣,我們就找到了一個(gè)能夠用真正不依賴于 GUI 的方式來實(shí)現(xiàn)和編寫用例的方案。 那么,實(shí)現(xiàn)這些用例控制器對象,您有哪些選擇呢?因?yàn)樗鼈兲焐捅仨毷怯袪顟B(tài)的,我們有兩個(gè) J2EE 體系結(jié)構(gòu)中自己提供的選擇: 一個(gè)選擇是把用例控制器變?yōu)榭尚蛄谢瘜ο螅↗avaBeans),然后在 HttpSession 中存儲(chǔ)和檢索它們。當(dāng)然,這只能用在使用 Servlet API 的應(yīng)用程序中。但它可以應(yīng)用于很多應(yīng)用程序,甚至包括那些使用 Applet 和 Application 的客戶機(jī) GUI 的應(yīng)用程序,因?yàn)榧词乖谶@些情況下,通過 HTTP(也可能使用 SOAP)來和服務(wù)器端對象進(jìn)行通信也是一個(gè)常用的設(shè)計(jì)策略。用 HttpSession 作為存儲(chǔ)機(jī)制會(huì)使程序員更輕松,因?yàn)樵诙鄶?shù)應(yīng)用服務(wù)器(例如 WebSphere)中會(huì)話的持久和故障轉(zhuǎn)移細(xì)節(jié)都是自動(dòng)處理的。然而,在 WebSphere 中,一個(gè) HttpSession 要得到合理的持久性,則其大小將受到一定的限制(請參閱 Gunther ),所以這個(gè)選擇只適合用例控制器對象相對較小的情況。 另一個(gè)選擇是把有狀態(tài)的Session bean 當(dāng)作用例控制器用。有狀態(tài)的Session bean 是個(gè)很好的解決方案,它使程序員不必?fù)?dān)心如何維護(hù)會(huì)話信息。在有狀態(tài)的Session bean 被自動(dòng)存儲(chǔ)在共享持久存儲(chǔ)器的應(yīng)用服務(wù)器中,這個(gè)解決方案甚至能處理故障轉(zhuǎn)移。但是,在像 WebSphere 這樣的應(yīng)用服務(wù)器中的Session bean 并不存儲(chǔ)在共享持久存儲(chǔ)器中,如果碰上服務(wù)器崩潰,這個(gè)解決方案將導(dǎo)致用戶會(huì)話失敗。而且,以這種方式使用有狀態(tài)的Session bean 會(huì)使我們回到增大總的分布截面的老問題上。盡管如此,由于有狀態(tài)的Session bean 自己充當(dāng)一個(gè) facade,每個(gè)客戶機(jī)只需知道少數(shù)的用例控制器,這樣就減輕了這個(gè)問題。 繞了個(gè)圈,這種模式又把我們帶回到我們最初討論的 Facade 模式。這種模式相繼分層的方式使我們可以集中精力處理手邊的工作,同時(shí)還允許我們重用一些東西來構(gòu)成我們的解決方案。我們不必一次性設(shè)計(jì)出整個(gè)系統(tǒng),但可以反復(fù)使用這些模式,然后看著一套可重用的對象作為結(jié)果出現(xiàn)。 總結(jié) 我在本文中簡要分析了構(gòu)建Session Facade 的一些規(guī)則。您已經(jīng)看到了該如何組織Session Facade 所調(diào)用的對象,如何著手設(shè)計(jì)Session Facade。您還看到了設(shè)計(jì)能與Session facade 配合得很好的用例控制器的一些方法。我希望,這些規(guī)則的應(yīng)用能提高您的 EJB 設(shè)計(jì)的適應(yīng)性和性能。 致謝 感謝 Martin Fowler 審讀了本文的草稿并提出了深刻的意見。同時(shí)感謝 Craig Larman 的深刻見解,他使我明白事實(shí)上Session facade 有兩種互補(bǔ)模式。 參考書目 Erich Gamma、Richard Helms、Ralph Johnson 與 John Vlissides 合著的 Design Patterns: Elements of Reusable Object-Oriented Design,Addison-Wesley,1995。 Gamma Martin Fowler 的 Analysis Patterns: Reusable Object Oriented Model,Addison-Wesley,1997。 Fowler Martin Fowler 的 Information Systems Architectur。[Fowler 2001] Sherman Alpert、Kyle Brown 與 Bobby Woolf 合著的 The Design Patterns Smalltalk Companio,Addison-Wesley,1996。 Alpert William Brown、Ralph Malveau、Hays McCormick 與 Thomas Mobray 合著的 AntiPatterns: Refactoring Software, Architectures, and Projects in Crisis,John Wiley and Sons,1998。[Brown 1998] Kyle Brown、Philip Eskelin 與 Nat Pryce 合著的 “A small pattern language for Distributed Component Design,是提交給 1999 年在 Illinois 的 Monticello 召開的程序模式語言(the Pattern Language of Programs,PloP)大會(huì)的論文,在 Ratio Group Web site 有它的完整鏡像發(fā)布。[Brown 1999] Kyle Brown 的 “Layered Architectures for EJB System,VisualAge Developer Domain。[Brown 2000] Kyle Brown 的 “Choosing the right EJB type:Some Design Criteria,VisualAge Developer Domain。[Brown 2000a] Kyle Brown 與 et. al. 合著的 Enterprise Java Programming for IBM WebSphere,Addison-Wesley Longman,Boston,2001 年 5 月。[Brown 2001] “Session Facade, Sun Java 核心 J2EE 模式,Java 開發(fā)者連接。[Sun 2001] Harvey Gunther 的 “WebSphere Application Server Development Best Practices for Performance and Scalability。 Gunther “Session Enity Facade,Sun J2EE 規(guī)劃藍(lán)圖。[Sun 2000] Sun Microsystems,“EJB 2.0 規(guī)范,發(fā)布草案 2。[EJB 2.0] Richard Monson-Haefel,Enterprise JavaBeans,第二版,O&acute;Reilly,2000。[Monson-Haefel] Ivar Jacobson 與 et.al 合著的 “The Unified SoftWare Development Process,Addison-Wesley,1999。[Jacobson 1999] 腳注 1 Erich Gamma、Richard Helms、Ralph Johnson 與 John Vlissides 合著的 Design Patterns: Elements of Reusable Object-Oriented Design,Addison-Wesley,1995,第 185 頁。 2 Erich Gamma、Richard Helms、Ralph Johnson 與 John Vlissides 合著的 Design Patterns: Elements of Reusable Object-Oriented Design,Addison-Wesley,1995,第 186 頁。 3Erich Gamma、Richard Helms、Ralph Johnson 與 John Vlissides 合著的 Design Patterns: Elements of Reusable Object-Oriented Design,Addison-Wesley,1995,第 187 頁。 4Erich Gamma、Richard Helms、Ralph Johnson 與 John Vlissides 合著的 Design Patterns: Elements of Reusable Object-Oriented Design,Addison-Wesley,1995,第 193 頁。 5William Brown、Ralph Malveau、Hays McCormick 與 Thomas Mobray 合著的 AntiPatterns: Refactoring Software, Architectures, and Projects in Crisis,John Wiley and Sons,1998,第 73 頁。 關(guān)于作者 Kyle Brown 是 IBM WebSphere Service 的高級 Java 顧問。Kyle 在 WebSphere Service 中的職責(zé)是就關(guān)于面向?qū)ο蟮闹黝}和Java 2 企業(yè)版(J2EE)技術(shù),向“財(cái)富 500 強(qiáng)客戶提供咨詢服務(wù)、教育以及指導(dǎo) 。他是 The Design Patterns Smalltalk Companion(設(shè)計(jì)模式 Smalltalk 伴侶)的合著者,也是一位著名的撰稿人,還是關(guān)于 Enterprise Java,OO 設(shè)計(jì)和設(shè)計(jì)模式主題的討論會(huì)的發(fā)言人??赏ㄟ^ brownkyl@us.ibm.com 與 Kyle 聯(lián)系。 Java, java, J2SE, j2se, J2EE, j2ee, J2ME, j2me, ejb, ejb3, JBOSS, jboss, spring, hibernate, jdo, struts, webwork, ajax, AJAX, mysql, MySQL, Oracle, Weblogic, Websphere, scjp, scjd
相關(guān)文章:
主站蜘蛛池模板: 国产精品自拍av | 国产一区二区三区色淫影院 | 久久国产精彩视频 | 国产区在线观看 | 观看毛片 | 伊人网伊人网 | 欧美一级电影免费观看 | 国产在线观 | aaaaa毛片 | 91日韩| 91天堂 | 欧美成人免费在线 | 91网站在线观看视频 | 亚洲国产精品一区 | 成年免费大片黄在线观看一级 | 亚洲在线 | 秋霞电影一区二区三区 | 91欧美激情一区二区三区成人 | 亚洲成人www | 在线91| 三级av在线 | 激情网站在线观看 | 龙珠z国语版在线观看 | 日韩中文字幕 | 欧美精品乱码久久久久久按摩 | 久久精品99国产精品 | 国产高清视频在线观看播放 | 久亚州在线播放 | 午夜免费在线电影 | 日韩av在线免费 | 亚洲精品日韩精品 | 人人玩人人添人人澡欧美 | 国产欧美精品一区二区 | 午夜视频在线观看一区二区 | a亚洲精品| 亚洲精品国产a久久久久久 午夜影院网站 | 亚洲精品久久视频 | 99亚洲精品视频 | 无人区国产成人久久三区 | 国产精品美女久久久久久免费 | 天堂在线www |