作為最常用的建立模式,Factory模式在這裡起到連接配接接口和實作的橋梁作用。通過Factory模式,我們可以根據具體需要加載相應的實作,并将此
實作作為所對應接口的一個執行個體提供給業務層使用:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
CustomerDao custDAO = (CustomerDAO)DAOFactory.getDAO(CustomerDAO. class );
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
Customer customer = custDAO.getCustomer(customerID);
通過上面的代碼我們可以看到,通過接口我們将具體的DAO實作類從碼中分離。
也就是說,業務層通過接口調用底層實作,具體的DAO實作類不會出現在我們的業務代碼中。而具體實作類在配置檔案中加以配置,之後
DAOFactory.getDAO方法通過讀取配置檔案獲得目前我們期望使用的實作類的類名,再通過Java Class動态加載機制加載後傳回。
進而我們的代碼并不依賴某個特定的實作類,隻需要在部署的時候在配置檔案中指定目前采用的實作類即可。
本例中,為了提高性能,避免每次調用都讀取配置檔案所引起的大量磁盤操作,采用HashMap作為DAO緩存實作示例:
public class DAOFactory ... {
private static HashMan daoMap=null;
//return a implementation instance of the specified DAO Interface
//return the DAO Implemenation Class Instance
public static Object getDAO(Class daoInterface)...{
initial();
Object dao=doMap.get(daoInterface);
if(null==dao)...{
throw new DAOException ("No Implementation found of DAO inter+daoInterface.getName());
}
return dao;
}
public static synchronized void initial()...{
if(null==daoMap)...{
daoMap=DaoConfig.load();//根據配置檔案中加載DAO實作配置
}
}
}
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
DAOConfig類實作了配置檔案的讀取功能,并根據配置檔案中的内容加載指定的接口和實作類:
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);
JFigIF daoConfig=JFig.getInstance(jfigLocator);
Properties prop = daoConfig.getSectionAsProperties(DAO_CONFIG_SECTION);
Enumeration enumSection=prop.keys();
while(enumSection.hashMoreElements())...{
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(ClassNotFountException e)...{
logger.debug("No Class Found =>"+e);
}
}
return map;
}
}
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
一個示例配置檔案如下:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
<? xml version ="1.0" encoding="UTF-8" ?>
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
< configuration >
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
< section name ="DAO" >
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
< entry key ="net.xiaxin.lab.persistence.dao.iface.CustormerDAO"
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
value ="net.xiaxin.lad.persistence.dao.impl.CustomerDAOImpl_Mysql" />
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
< entry key ="net.xiaxin.lab.persistence.dao.iface.PromotionDAO"
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
value ="net.xiaxin.lab.persistence.dao.impl.PromotionDAOImpl_Mysql" />
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
</ section >
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
</ configuration >
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
DAOConfig中使用了JFig讀取XML配置檔案(dao.xml)。關于JFig的具體資訊請參見Http://jfig.sourceforge.net
ClassToolKit.loadClass方法實作了類檔案的動态加載:
public class ClassToolKit ... {
public static class loadClass(String className)throws ClassNotFoundException...{
Class cls=null;
try...{
cls=Thread.currentThread().getContextClassLoader().loadClass(className);
}catch(Exception e)...{
e.printStackTrace();
}
if(cls==null)...{
cls=Class.forName(className);
}
return cls;
}
}
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
經過Factory模式的改造,我們的業務層代碼也進行了相應的改造:
public BigDecimal calcAmount(String custormerID,BigDecimal amount) ... {
CustomerDAO customerDAO=(CustomerDAO)DAOFactory.getDAO(CustomerDAO.class);
Customer customer= customerDAO.getCustomer(customerId);
PromotionDAO promoDAO=(PromotionDAO)DAOFactory.getDAO(PromotionDAO.class);
Promotion promotion=promoDAO.getPromotion(customer.getLevel());
customer.setSumAmount(customer.getSumAmount().add(amount));
customerDAO.save(customer);
return amount.multiply(promotion.getRatio());
}
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
相對于改造前,這些代碼裡混雜了一些資料通路層的内容,如DAOFactory.getDAO方法的調用
Proxy模式的作用是通過提供一個中間層(Proxy),将上層調用接口與下層實作相銜接,先看Proxy模式改造的業務層代碼
public BigDecimal calcAmount(String custormerID,BigDecimal amount) ... {
Customer customer= CustomerProxy.getCustomer(customerId);
Promotion promotion=PromotionProxy.getPromotion(customer.getLevel());
customer.setSumAmount(customer.getSumAmount().add(amount));
customerDAO.save(customer);
return amount.multiply(promotion.getRatio());
}
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
Bad Smell消失了,業務層也清潔了,而CustomerProxy和PromotionProxy做了些什麼呢?
public class CustomerProxy ... {
public static Customer getCustomer(String customerID)...{
CustomerDAO custDAO=(CustomerDAO)DAOFactory.getDAO(CustomerDAO.class);
return custDAO.getCustomner(customerID);
}
public static void save(Customer customer)...{
CustomerDAO custDAO=(CustomerDAO)DAOFactory.getDAO(CustomerDAO.class);
custDAO.save(customer);
}
}
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
public class PromotionProxy ... {
public static Promotion getPromotion(int level)...{
PromotionDAO promoDAO=(PromotionDAO)DAOFactory.getDAO(PromotionDAO.class);
return promoDAO.getPromotion(level);
}
}
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIml2ZuUmbv50LcNncvRXYjlGZul0ZulmbpxGd190LcdmbpRHanlGbodWaohXY05Wez9CX0Vmbu4GZzNmLzV2Zh1Wavw1LcpDc0RHaiojIsJye.gif)
摘自《深入淺出Hibernate》