Session Facade 的規則和模式

來源:互聯網
上載者:User

 

Kyle Brown

Java 執行設計師,IBM WebSphere Service

2001 年 6 月

在過去幾年中,Enterprise JavaBeans(EJB)確實已經開始對 Java 對象設計產生影響。期間,我們看到的最常使用的 EJB 模式之一是Session Facade 概念。這是一個讓很多開發人員都受益匪淺的既強大又非常簡單的概念。然而,我也看到,對這一模式的確切含義及其在實踐中的應用,人們仍有很多誤解。

為了把這個問題講得更明白些,我會在本文中講述 Facade 的一些基本概念以及Session Facade 模式的工作機制,並探討該模式衍生出來的一些問題。希望能藉此澄清一些誤解,並協助開發人員正確使用這種模式。

什麼是Session Facade?您又為什麼需要它?

很多地方都有對Session Facade 模式的清楚描述,也就是 [Sun 2001] 和 [Brown 2000]。我不想照抄那裡的全部內容,而打算把它的理論在此作個總結:基本的問題是在 EJB 設計中,EJB 客戶機(例如,Servelet、Java 應用程式,等等)不可直接存取 Entity bean。

之所以如此,有以下幾個原因:

  • 當依靠 RMI-IIOP 進行跨越網路的調用時運行態的效能會受到極大影響。如果客戶機請求一個Entity bean 去表示如包含兩項資料(比方說帳戶餘額和帳戶所有者姓名)的銀行帳戶,則將需要兩個網路調用。當大量屬性使網路調用成倍增加時,很快這些開銷就會變得非常明顯。[Monson-Haefel] 中所說的批量訪問器(bulk accessors)或許是一種解決方案,所謂批量訪問器,就是Entity bean 上的一些方法,它們建立並傳回值對象以表示Entity bean 中的資料。它事實上就是 Java VisualAge 的 CopyHelper Access Beans 採用的解決方案。但是,它有一個令人遺憾的缺陷,就是它假設所有的請求都需要 EJB 中的“所有”資料,結果為使用者返回了一些不必要的資料,並導致對更大的值對象進行組織和分解時產生額外開銷。

  • 更重要的是,如果您允許 EJB 客戶機直接存取Entity bean,那麼就要求客戶機瞭解Entity bean 的內部方法,而這已經超出了客戶機的應知的範圍。例如,操作一個Entity bean 需要知道所涉及到的該實體的關係(關聯,繼承),這樣就把業務模型的所有細節不適當地暴露給了客戶機。另外,操作多個Entity bean 會要求使用用戶端事務 — 這是另一個使事情複雜化的因素,這意味著 EJB 可能要被從客戶機設計中除去,而不是添加上去。

大多數設計師已經發現為了在 EJB 設計中避免直接存取Entity bean 的解決方案都可以在 [Gamma] 中描述的 Facade 中找到。[Gamma] 這樣描述 Facade 模式:“為子系統中的一套介面提供了一個統一的介面。Facade 定義了一個更高層次的介面,使子系統更容易使用。”1在 EJB 中應用這種思想一般意味著您應該建立一個擔當 Facade 的Session EJB,然後把構成子系統的一套Entity bean “封裝”起來。這樣,客戶機就和Entity bean 實現的細節分離開來了,而且不必自己管理交易管理的細節。

但問題是有很多人到此就打住了。然後他們輕鬆地往下做,開始把Entity bean 封裝到Session bean 中,而不考慮 Facade 模式所描述的其它內容以及 EJB 設計中由 Facade 模式衍生出來的問題。這很可能是由於把得到的 Facade 的“二手”資訊都當真,而沒去研究原始模式的緣故。如果我們確實花了些時間去理解 Facade 衍生的問題,我們將可以看到很多該模式所固有的其它有益的設計可能性。

Facade 模式的要點

[Gamma] 中描述了很多我們應該瞭解的 Facade 模式的要點。前面幾點可在 Facade 模式的“適用性”描述部分找到,它描述了在什麼情況下您會需要應用該模式。它們是:“當您想為複雜的子系統提供一個簡單介面時……請使用 Facade 模式”和“當您想把子系統分層時……請使用 Facade 模式。使用 Facade 為每一層子系統定義一個進入點。”2

從對 Facade 模式的討論中,我們可以提煉出兩個觀點。第一點是 Facade 應該提供子系統的一個抽象視圖,而不是簡單地把整個子系統本身的 API 直接封裝起來。不幸的是,我在實際中多次看到開發人員建立的Session bean 把Entity bean home 和Entity bean 對象的全部方法直接封裝起來,而不提供任何額外的抽象,這是對該模式最可惡的濫用情況之一。請記住,這種思想是想降低整個系統的複雜性,而不是把複雜性轉移到另一個對象上。

第二點,也是更微妙的一點,與分層有關。這個觀點認為您可以用多重 Facade 來隱藏下層子系統的細節。因此,在這裡您可以這樣設想,Session Facade 應該在其它 Facade 之上,位於最上層,是對底層商務邏輯細節的進一步抽象。這一點很關鍵。當您看完下面兩條(分別出自 [Gamma] 中論述 Facade 模式的“協作”和“相關模式”部分)敘述後,就會更加清楚這一點:

  • “客戶機通過把請求發送給 Facade,再由 Facade 把請求轉寄給適當的子系統對象來與子系統通訊。”3
  • “facade 只是對通往子系統對象的介面進行抽象以使它們更便於使用;它不定義新功能。”4

我把這幾點總結如下:Facade 不做系統的實際工作;而是委託其他對象輪流做這個工作。由此推理出您必須正確地放置這些對象,以便使該模式能按照您所期望的運行。

這一點是本模式的兩種流行表達 [Sun 2000] 和 [Sun 2001] 之間的主要不同之處。第一個版本,即 [Sun 2000],是 J2EE 規劃的一部分,它把這種模式稱為“Session Entity Facade”。它意在表明“為一堆企業 beans 提供單一的介面”。它描述了這樣一種模式,即所有的資料存取都通過Entity bean 來完成,Session bean 則為這些Entity bean 提供介面。現在的問題是 [Sun 2000] 不一定非要以 EJB 為中心。它根本不涉及其它物件類型,並且假設系統中只有 EJB 一類對象。根據我的經驗,我認為這會導致根本不能在工程間重用的臃腫的Session對象,而且,在同一個工程內,當需求有一點不同時就會出現問題。

現在,[Sun 2001] 則更通用,也沒有上述問題的困擾。它簡單地把這種模式稱為“Session Facade”。它的解決方案規定您應該“把Session bean 當作 facade 來用,以封裝參與工作流程的業務對象之間的互動操作的複雜性”。它根本不限制您的業務對象應該為 EJB,因此是一個更加靈活的方法。

Session Facade 的重要規則

那麼我們該如何應用這些關於針對會話的 Facade 的規則呢?這對我們的 EJB 設計又意味著什麼呢?我在設計Session Facade 時遵循三條基本原則:

  • 它們自己不做實際工作;它們委派其它對象做實際工作。這意味著Session facade 中的每個方法都應該很小(異常處理邏輯不計算在內,代碼應為五行或更少)。
  • 它們提供簡單的介面。這意味著 facade 方法的數量應相對較少(每個Session bean 中僅有約 24 個)。
  • 它們是底層系統的用戶端介面。它們應該把特定於子系統的資訊封裝起來,並且不應該在不必要的情況下公開它。

那麼它的工作機制呢?您還能代理別的哪些類型的對象呢?這又會給您的設計帶來什麼好處呢?在我的一篇早期論文和 [Brown 2001] 這本書中,我已論述了其中一些問題,在那裡可以找到一些詳細資料。但,總的來說,在我的多數 EJB 設計中我通常會找到以下四類對象:

  • 值對象是包含了客戶機所請求的資料的、可序列化的 Java bean。它包含Entity bean 和其他資料來源所包含的資料的一個子集。它是Session EJB 方法的傳回型別。[EJB 2.0] 和 [Sun 2001] 都描述了值對象和值對象的用途。請注意 [Fowler 2001] 稱其為“資料轉送對象”( Data Transfer Objects ),[Brown 1999] 也使用這個名稱。我個人覺得資料轉送對象是描述性更好的術語,但不幸的是,Sun 的術語似乎更通用。
  • 對象製造廠 (Factory) [Brown 1999] [Brown 2000] 負責構建值對象。它能完成辨別不同的資料來源、建立值對象的執行個體、填儲值對象的執行個體等等工作。每個 factory 類 都可以從多個資料來源中檢索資料或更新其中的資料。在您的物件模型中,每個“根”對象都應該有一個 factory 類。(根對象是那些“包含”其它對象的對象。)從某種意義上說,對象 Factory 類在 JDBC 或持久的 Entity bean 子系統上擔當 Facade,實現 [Gamma] 中提到的分層原則。
  • Entity EJB 應該是標準的、企業全域範圍內可用的“資料來源”。Entity bean 不應包含特定於應用程式的域邏輯,也不應限制為只能在單一應用程式內工作。請注意Entity bean 是可選的,它不是這種體繫結構中必需的部分;Factory 可能像 JMS 隊列或 JDBC 串連那樣簡單地直接從資料來源擷取資料。
  • Action 對象是Session bean 可能調用的唯一對商業業務進行處理的對象。Action 對象只處理與簡單的建立、讀取、更新或刪除資料無關的商業流程。和對象 Factory 一樣,Action 對象也充當內層 Facade。

一個 EJB 對象樣本

描述類似這樣的模式遇到的一個問題是,能夠使用這種模式的樣本都太大,以至於無法包含在模式自身的描述中。儘管如此,我還是要嘗試舉出如下樣本(它顯然很簡單)來說明一下這些對象看起來是什麼樣子。

假設我們正在為銀行構建一個 ATM 系統。這是最老掉牙的 OO 設計問題之一,當然其它很多書籍和論文已經討論過它,但它確實有足夠符合我們要求的有趣特點。通過分析,我們發現了兩種 EJB。

  • 從 ATM 到銀行的串連表示為Session bean。該 bean 上有一些方法負責處理您通過 ATM 可以完成的交易 — 存款、取款以及帳戶間的資金轉移。
  • 帳戶表示為Entity bean(我們的樣本採用 CMP,但它在我們的樣本中實際上並沒什麼影響)表示。它有返回帳戶餘額、對帳戶進行借貸處理的方法。

ATM Session bean 的遠程介面如下:

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 的遠程介面如下:

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;

}

現在,我們還發現有另外兩種物件類型對我們的系統是有用的。第一種是描述顯示在 ATM 機上的帳戶資訊的值對象。這個類看起來如下所示:

public class AccountValue implements java.io.Serializable { private java.lang.String accountNumber; private double balance; }

當然,AccountValue 類也有作為屬性的 getter 和 setter 的方法,但我們暫時不考慮它們。

現在,我們基本上有了足夠的資訊來理解 ATM EJB 的 getAccounts() 方法的實現。這個方法的實現如下:

public java.util.Vector getAccounts(String userid) throws FactoryException { AccountFactory fact = new AccountFactory(); Vector result = fact.getAccounts(userid); return result; }

這個方法展示了Session Facade EJB 的方法的標準模式。它找到合適的協助對象(Action 或 Factory,在本例中是 Factory),調用協助對象上的業務方法,然後返回結果。

如這個方法所指出的,我們需要一個 AccountFactory 類來從 Accounts 構建 AccountValues。這個類的類定義如下:

public class AccountFactory { private static AccountHome accountHome = null; }

AccountFactory 的 getAccounts(userid) 方法的實現如下:

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); } }

這個方法使用一個快取的 AccountHome 執行個體,它是從以下方法中擷取的:

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 中,快取 EJB home 是一個極好的習慣,因為擷取 JNDI InitialContext 和從 InitialContext 擷取 EJB Home 需要一段時間。

既然您已經看到了Session、Entity和 Factory 如何組合在一起,那我們就來看一個 Action 類的樣本。在本例中,我們有一個處理從一個帳戶到另一個帳戶的資金轉移的 Transfer 對象。Transfer 由 ATM EJB 中的 transfer() 方法的實現中建立,該方法的實現如下:

public void transfer(String fromAccount, String toAccount, double amount) throws InsufficientFundsException, FactoryException { Transfer trans = new Transfer(); trans.transfer(fromAccount, toAccount, amount); }

請再次注意同樣的流程。不過,這個方法不必從 Action 對象傳回值。Transfer 類的定義如下:

public class Transfer { private static AccountHome accountHome; }

transfer() 方法的實現如下:

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); } }

您已經看到,Transfer 對象中的 transfer() 方法處理以下細節:定位兩個 Account 實體,確保“From”帳戶有足夠的餘額,把轉移金額存入“To”帳戶,從“From”帳戶中提出轉移金額。同樣地,您可以看到 Action 對象的其它方法可以實現您系統中的其它商務規則。

使用 EJB 對象的原因

那麼為什麼我們需要這第二層對象呢?難道我們從 CORBA 和 RMI 轉到 Enterprise JavaBean 就使事情更簡單了嗎?為什麼不把所有的邏輯都放到 EJB 中呢?這有幾個原因。第一個也是最重要的原因是這是一個分層應用程式。在單個對象中放置太多工作從來不是一個好主意。如果您用這種方式來布置由 EJB 調用的對象,可以帶來以下好處:

  • 把工作放在一個會話層上的一套對象中,使我們可以更容易獨立地測試它們,或許甚至可以在 J2EE 應用伺服器環境之外對它進行測試。
  • 不同的多個Session Facade 對象可以使用同一層上的對象,而不必擔心事務語義不正確,也沒有跨Session bean 調用可能帶來的網路和資料群組織/資料分解開銷。
  • 第二層對象允許您對那些對象實現多樣化(通過使用 [Gamma] 中介紹的 Stragtegy 模式),這樣便可以利用應用伺服器的特有功能,同時仍然保持整個設計在應用伺服器之間的可移植性。例如,[Brown 2000a] 描述了一些特別的快取策略,用於提高那些能在 WebSphere Application Server(進階版)下工作、卻不能在 IBM CICS EJB 支援下工作的 EJB 的效能。通過為同一個 Factory 類或 Action 類提供兩個實現,您便可以保持整個設計的可移植性,同時也最大程度地利用各個伺服器的特有功能。
  • 在您不需要 JTA 事務的情況下(例如,您只對單一資料來源進行操作),這個模式允許您選擇部署和構建帶或不帶 EJB 的應用程式。例如,在一些簡單查詢中,為避免 EJB 調用的開銷,您可以直接從 servlet 調用 Factory,這能顯著提高效率。

同時,通過回顧幾個工程,我們發現重用只在少數情況下會出現在會話層上。這是因為,每個會話都有針對一個特定應用程式的一個事務設定與方法的特定組合。有了第二層對象則使您可以在內層層級上進行重用,我們在很多工程中都看到過這種重用,包括在企業的一個工程內(在不同的Session bean 之間)和多個工程之間。

我們已經看到,如果採用這種策略,那麼您的設計經常可以把無狀態Session bean 當作 Facade 對象使用。由於對某個使用者而言,每個無狀態Session bean 都不是唯一的,這就使您能夠得到無狀態 bean 所提供的另外的可擴充性。

既然我們已經知道了 facde 背後對象的類型,我們就可以開始看看 facade 能對外提供哪些類型的方法了。我們看到 Facade 方法通常屬於以下幾種類型:

  • Collector 方法通常以“get”開頭,返回一個對象或一個對象集合(在 EJB 1.0 中是 Emulation,在 EJB 1.1 和 2.0 中則是一個 Java Collection)。如 [Brown 2000] 所述,collector 方法在 Factory 對象中實現。
  • Updater 方法根據作為參數傳入的值對象所掌握的資訊來定位並更新一個Entity bean 或一個Entity bean 集。方法名稱常常以“update”或“set”開頭。updater 方法的實現可以像 [Brown 2000] 所說的那樣放在 factory 中,或者在一個單獨的類中。
  • Action 方法(例如 transfer(String fromAcctNum, String toAcctNum, BigDecimal amount))的實現放在 Action 對象中。

Session Facade 的建立規則

既然您看到了Session Facade 介面的樣子,在Session Facade 背後的又有哪些對象,那麼下一個問題就是“我該有多少Session Facade 呢?”您不應擁有太多的Session Facade,否則,就喪失了 Facade 模式帶來的好處。但是,若整個應用程式對應一個Session Facade 它可能會成為一個“巨大的對象”5並導致它自身的一些問題。這裡是設計Session Facade 的一些規則,使您能適當地(不過多或過少)使用它。

  • 從您的應用程式中找出功能子系統。例如,名為定單管理、帳單管理和運輸管理的子系統就是一個應用程式中可能有的三個 Facade 對象。
  • 回到您的用例(Use-case)和相關的用例組。一組相關的用例 (例如購買股票、出售股票和擷取報價)可以形成一個內聚子系統,例如“股票交易”。這個內聚子系統就可能要共用很多內層對象,並且是使用Session Facade 的最佳候選。[Sun 2001] 更深入地討論了這個問題。
  • 千萬不要把所有的單個用例都做到Session Facade 中。這將導致系統分布截面過大。這種情況下,客戶機將不得不管理非常多的 EJB 引用和 Home。
  • 完成初步工作後,看一下您的設計中第二層對象之間的關係。如果您看到有值對象、Factory 和 Action 的不相交組,那就根據實際分組法把 Facade 分成兩個或更多 facade。

另一種會話模式

既然您已深信應該使用無狀態的Session Facade 來封裝資料來源,也應該在這些 facade 的實現中進行嚴格的分層,您可能會想知道特定於使用者的應用程式狀態(如果有的話)將被儲存在什麼地方。根據我所主張的把Session facade 設計成能處理多用例請求,您可能還會想知道用例在哪裡實際實現。

為了理解如何應用它,我們採用出自 [Jacobson 1999] 的 Control 對象的如下定義:“Control 類代表協調、順序事務以及對其它對象的控制,常用於封裝與特定用例相關的控制。”

這個解決方案的目標是實現專門的、與一個單一的用例一一對應的“用例控制器”對象。每個用例控制器都將維護一些特定於使用者的狀態,這些狀態與判斷一個使用者在此用例中位於哪裡所必需的資訊(例如,它們已經執行了多少)相對應,也與使用者輸入的、對執行用例的下一步來說必需的資訊相對應。這樣,我們就找到了一個能夠用真正不依賴於 GUI 的方式來實現和編寫用例的方案。

那麼,實現這些用例控制器對象,您有哪些選擇呢?因為它們天生就必須是有狀態的,我們有兩個 J2EE 體繫結構中自己提供的選擇:

  • 一個選擇是把用例控制器變為可序列化對象(JavaBeans),然後在 HttpSession 中儲存和檢索它們。當然,這隻能用在使用 Servlet API 的應用程式中。但它可以應用於很多應用程式,甚至包括那些使用 Applet 和 Application 的客戶機 GUI 的應用程式,因為即使在這些情況下,通過 HTTP(也可能使用 SOAP)來和伺服器端對象進行通訊也是一個常用的設計策略。用 HttpSession 作為儲存機制會使程式員更輕鬆,因為在多數應用伺服器(例如 WebSphere)中會話的持久和容錯移轉細節都是自動處理的。然而,在 WebSphere 中,一個 HttpSession 要得到合理的持久性,則其大小將受到一定的限制(請參閱 [Gunther]),所以這個選擇只適合用例控制器對象相對較小的情況。

  • 另一個選擇是把有狀態的Session bean 當作用例控制器用。有狀態的Session bean 是個很好的解決方案,它使程式員不必擔心如何維護會話資訊。在有狀態的Session bean 被自動儲存在共用持久儲存空間的應用伺服器中,這個解決方案甚至能處理容錯移轉。但是,在像 WebSphere 這樣的應用伺服器中的Session bean 並不儲存在共用持久儲存空間中,如果碰上伺服器崩潰,這個解決方案將導致使用者會話失敗。而且,以這種方式使用有狀態的Session bean 會使我們回到增大總的分布截面的老問題上。儘管如此,由於有狀態的Session bean 自己充當一個 facade,每個客戶機只需知道少數的用例控制器,這樣就減輕了這個問題。

繞了個圈,這種模式又把我們帶回到我們最初討論的 Facade 模式。這種模式相繼分層的方式使我們可以集中精力處理手邊的工作,同時還允許我們重用一些東西來構成我們的解決方案。我們不必一次性設計出整個系統,但可以反覆使用這些模式,然後看著一套可重用的對象作為結果出現。

總結

我在本文中簡要分析了構建Session Facade 的一些規則。您已經看到了該如何組織Session Facade 所調用的對象,如何著手設計Session Facade。您還看到了設計能與Session facade 配合得很好的用例控制器的一些方法。我希望,這些規則的應用能提高您的 EJB 設計的適應性和效能。

致謝

感謝 Martin Fowler 審讀了本文的草稿並提出了深刻的意見。同時感謝 Craig Larman 的深刻見解,他使我明白事實上Session facade 有兩種互補模式。

參考書目

  • 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)大會的論文,在 Ratio Group Web site 有它的完整鏡像發布。[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 開發人員串連。[Sun 2001]
  • Harvey Gunther 的 “WebSphere Application Server Development Best Practices for Performance and Scalability”。[Gunther]
  • “Session Enity Facade”,Sun J2EE 規劃藍圖。[Sun 2000]
  • Sun Microsystems,“EJB 2.0 規範”,發布草案 2。[EJB 2.0]
  • Richard Monson-Haefel,Enterprise JavaBeans,第二版,O'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 頁。

關於作者

Kyle Brown 是 IBM WebSphere Service 的進階 Java 顧問。Kyle 在 WebSphere Service 中的職責是就關於物件導向的主題和Java 2 企業版(J2EE)技術,向“財富 500 強”客戶提供諮詢服務、教育以及指導 。他是 The Design Patterns Smalltalk Companion(設計模式 Smalltalk伴侶)的合著者,也是一位著名的撰稿人,還是關於 Enterprise Java,OO 設計和設計模式主題的討論會的發言人。可通過 brownkyl@us.ibm.com 與 Kyle 聯絡。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.