DAO模式實際是2個模式的組合,即Data Accessor和Domain Object模式
Data Accessor即將數據訪問的實現機制加以封裝,與數據的使用代碼相分離,從外部來看,Data Accessor提供了黒盒式的數據存取接口。Domain Object則提供了對所有面向領域內對象的封裝。
DAO模式實現了業務邏輯與數據邏輯的分離。對于專項開發而言,這樣的分離設計差不多已經可以實現開發過程中業務層面和數據層面的相對獨立,并且在實現復雜性與結構清晰性上達到較好的平衡。
對于一個產品化的業務系統而言,軟件產品往往需要在不同客戶環境下即時部署。由于java良好的跨平臺支持,我們在操作系統之間大可以輕易遷移,但在另外一個層面,數據庫層,卻仍然面臨著平臺遷移的窘境。針對不同的數據庫,我們可以實現針對不同類型數據庫的Data Accessor,并根據客戶實際部署環境,通過類文件的靜態替換來實現。這樣將大大增加部署和維護工作的難度和復雜性。我們應該將此類因素帶來的變動屏蔽在系統之外。
Factory模式在這里起到連接接口和實現的橋梁作用,通過Factory模式,我們可以根據具體需要加載相應的實現,并將此實現作為所對應接口的一個實例提供給業務層使用:
為了提高性能,避免每次調用都讀取配置文件所引起的大量磁盤操作,采用了HashMap作為DAO緩存實現示例:
public class DAOFactory{
private static HashMap daoMap = null;
public static Object getDAO(Class daoInterface){
initial();
Object dao = daoMap.get(daoInterface);
if(null == dao){
throw new DAOException();
}
return dao;
}
public static synchronized void initial(){
if(null==daoMap){
daoMap = DAOConfig.load();//根據配置文件加載DAO實現配置
}
}
}
public class DAOConfig{
private static Logger logger = LogManager.getLogger(DAOConfig.class);
private static final String DAO_CONFIG_FILE = "dao.xml";
private static final String DAO_CONFIG_SECTION = "DAO";
public static synchronized HashMap load(){
HashMap map = new HashMap();
JFigLocator jfigLocator = new JFigLocator(DAO_CONFIG_FILE);
Properties prop = daoConfig.getSectionAsProperties(DAO_CONFIG_SECTION);
Enumeration enumSection = prop.keys();
while(enumSection.hasMoreElements()){
String daoIface = (String)enumSection.nextElement();
String daoImpl = prop.getProperty(daoIface);
try{
Class iface = ClassToolkit.loadClass(daoIface);
Class impl = ClassToolkit.loadClass(daoImpl);
//將接口作為HashMap索引,實現類作為值
map.put(iface,impl);
}catch(ClassNotFoundException e){
logger.debug("No Class Found=>"+e);
}
}
return map;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<section name="DAO">
<entry key="net.xiaxin.lab.persistence.dao.iface.CustomerDAO" value="net.xiaxin.lab.persistence.dao.impl.CustomerDAOImp_Mysql"/>
<entry key="net.xiaxin.lab.persistence.dao.iface.PromotionDAO" value="net.xiaxin.lab.persistence.dao.impl.PromotionDAOImp_Mysql"
</section>
</configuration>
public class ClassToolkit{
public static Class loadClass(String className){
Class cls = null;
try{
cls = Thread.currentThread().getContextClassLoader().loadClass(className);
}catch(Exception e){
e.printStackTrace();
}
if(cls == null){
cls = Class.forName(className);
}
return cls;
}
}
業務層通過接口調用底層實現,具體的DAO實現類不會出現在我們的業務代碼中。而具體實現類在配置文件中加以配置,之后DAOFactory.getDAO方法通過讀取配置文件獲得當前我們期望使用的實現類的類名,在通過Java Class動態加載機制加載后返回。
通過接口與實現的分離,并結合DAOFactory動態加載實現類,我們實現了底層訪問實現的參數化配置功能。
無論有多好的理由,新的設計必須避免影響業務邏輯代碼的可讀性。沒有哪個物業公司能說服你在自己的房屋中增加一條穿堂而過的管道,而理由是為了實施更好的供暖設計,我們的軟件也一樣。
posted on 2009-10-06 09:23
王永慶 閱讀(160)
評論(0) 編輯 收藏 所屬分類:
HIBERNATE