EJB(Enterprise JavaBeans)作為企業級分散式元件框架,其核心目標是實現業務邏輯與資料存取的分離、支援多資料庫切換、降低維護成本。設計模式正是達成這些目標的關鍵工具。GoF 23 種經典模式在 EJB 中被廣泛應用,理解它們能讓開發者快速掌握 EJB 架構精髓。
兩者之間引入 DAO (Data Access Object) 層,實際上是 Bridge(橋接) 與 Adapter(適配器) 模式的混合體,將資料存取細節完全封裝。
角色對應:
CatalogEJB(業務邏輯)CatalogDAO 介面(資料存取抽象)CatalogDAOImpl(Oracle 具體實作)、可擴充 CatalogDAOImplMySQL 等程式碼片段:
// CatalogEJB - 業務邏輯層,完全不含 SQL
public class CatalogEJB implements SessionBean {
protected CatalogDAO dao;
public void ejbCreate() {
dao = CatalogDAOFactory.getDAO(); // 透過工廠獲取實作
}
}
// CatalogDAO - 定義資料存取契約
public interface CatalogDAO {
Category getCategory(String categoryID, Locale l);
Page getCategories(int start, int count, Locale l);
// ... 其他方法
}
// CatalogDAOImpl - Oracle 具體實作
public class CatalogDAOImpl implements CatalogDAO {
public Category getCategory(String categoryID, Locale l) {
// 這裡才出現具體 SQL、JDBC 程式碼
Connection c = getDataSource().getConnection();
PreparedStatement ps = c.prepareStatement("SELECT ...");
// ...
}
}
優勢:業務邏輯與資料庫實作解耦,新增資料庫只需新增 DAO 實作類,零修改業務層。
DAO 實作類內部使用 JDBC 驅動,透過組合/繼承將 JDBC 介面適配為統一的 DAO 介面,屏蔽底層差異。
// 動態工廠:從 JNDI 讀取實作類別名,支援熱插拔
public class CatalogDAOFactory {
public static CatalogDAO getDAO() throws CatalogDAOSysException {
InitialContext ic = new InitialContext();
String className = (String) ic.lookup(JNDINames.CATALOG_DAO_CLASS);
return (CatalogDAO) Class.forName(className).newInstance();
}
}
// 單例優化:若只需一個實例
public class CatalogDAOFactory {
private static CatalogDAO instance;
public static synchronized CatalogDAO getInstance() {
if (instance == null) { /* 初始化邏輯 */ }
return instance;
}
}
痛點:客戶端直接呼叫多個 Bean 導致耦合度高、網路開銷大、擴充困難。
解決方案:引入 ShoppingClientFacadeLocalEJB 作為統一進入點。
public class ShoppingClientFacadeLocalEJB implements SessionBean {
// 統一對外介面,內部委派給 CustomerEJB、ShoppingCartEJB 等
public CustomerLocal getCustomer() { /* 查找並委派 CustomerEJB */ }
public ShoppingCartLocal getShoppingCart() { /* 查找並委派 ShoppingCartEJB */ }
}
效益:客戶端單次 Remote 呼叫,Facade 內部本地呼叫鄰近 Bean,大幅降低網路延遲,提升擴充性。
在 EJB 專案中善用設計模式,不僅能實現程式碼重用與擴充,更能彌補 EJB 框架本身在效能上的短板,構建高效、可維護的企業級應用。