J2EE 應用常需存取多種持久化存儲(RDBMS、LDAP、檔案等),各資料源 API 差異大。若業務元件直接耦合 JDBC/SQL,遷移資料庫將面臨大規模重寫。
| 角色 | 職責 |
|---|---|
| BusinessObject | 業務邏輯元件,委託 DAO 存取資料 |
| DataAccessObject (DAO) | 封裝特定資料源存取細節,提供統一介面 |
| DataSource | 實體資料源(Oracle、MySQL、XML、LDAP...) |
| ValueObject (VO) | 資料傳輸載體,DAO 與 BusinessObject 間傳遞資料 |

結合 Abstract Factory / Factory Method,依資料源類型動態提供具體 DAO 實例。


| 優點 | 缺點 |
|---|---|
| 透明存取:業務邏輯不感知資料源細節 | 增加額外抽象層,略增複雜度 |
| 遷移容易:僅替換 DAO 實作或工廠 | 需設計完整類別階層(介面、實作、工廠) |
| 降低業務代碼複雜度:SQL 集中於 DAO | CMP Entity Bean 場景下容器已管理持久化,DAO 多餘 |
| 集中資料存取邏輯,利於維護 | 效能微幅開銷(通常可忽略) |
public abstract class DAOFactory {
public static final int CLOUDSCAPE = 1, ORACLE = 2, SYBASE = 3;
public abstract CustomerDAO getCustomerDAO();
public abstract AccountDAO getAccountDAO();
public abstract OrderDAO getOrderDAO();
public static DAOFactory getDAOFactory(int which) {
switch(which) {
case CLOUDSCAPE: return new CloudscapeDAOFactory();
case ORACLE: return new OracleDAOFactory();
case SYBASE: return new SybaseDAOFactory();
default: return null;
}
}
}
public class CloudscapeDAOFactory extends DAOFactory {
public static final String DRIVER = "COM.cloudscape.core.RmiJdbcDriver";
public static final String DBURL = "jdbc:cloudscape:rmi://localhost:1099/CoreJ2EEDB";
public static Connection createConnection() { /* 連線池實作 */ }
public CustomerDAO getCustomerDAO() { return new CloudscapeCustomerDAO(); }
public AccountDAO getAccountDAO() { return new CloudscapeAccountDAO(); }
public OrderDAO getOrderDAO() { return new CloudscapeOrderDAO(); }
}
public interface CustomerDAO {
int insertCustomer(...);
boolean deleteCustomer(...);
Customer findCustomer(...);
boolean updateCustomer(...);
RowSet selectCustomersRS(...);
Collection selectCustomersVO(...);
}
public class CloudscapeCustomerDAO implements CustomerDAO {
public int insertCustomer(...) { /* Cloudscape 專用 SQL */ }
public Customer findCustomer(...) { /* 回傳 ValueObject */ }
// ... 其他方法
}
public class Customer implements Serializable {
int customerNumber; String name; String streetAddress; String city;
// getter/setter
}
DAOFactory factory = DAOFactory.getDAOFactory(DAOFactory.CLOUDSCAPE);
CustomerDAO dao = factory.getCustomerDAO();
int id = dao.insertCustomer(...);
Customer c = dao.findCustomer(...);
c.setAddress(...);
dao.updateCustomer(c);
Collection list = dao.selectCustomersVO(criteria);
DAO 模式以「介面隔離實作、工廠解耦創建」為核心,配合 ORM 代碼生成或手工實作,能構建靈活、可遷移、易維護的企業級資料存取層。