天天看點

Factory模式,Proxy模式和持久層

 作為最常用的建立模式,Factory模式在這裡起到連接配接接口和實作的橋梁作用。通過Factory模式,我們可以根據具體需要加載相應的實作,并将此

實作作為所對應接口的一個執行個體提供給業務層使用:

Factory模式,Proxy模式和持久層

CustomerDao custDAO = (CustomerDAO)DAOFactory.getDAO(CustomerDAO. class );

Factory模式,Proxy模式和持久層

Customer customer = custDAO.getCustomer(customerID);

 通過上面的代碼我們可以看到,通過接口我們将具體的DAO實作類從碼中分離。

 也就是說,業務層通過接口調用底層實作,具體的DAO實作類不會出現在我們的業務代碼中。而具體實作類在配置檔案中加以配置,之後

DAOFactory.getDAO方法通過讀取配置檔案獲得目前我們期望使用的實作類的類名,再通過Java Class動态加載機制加載後傳回。

 進而我們的代碼并不依賴某個特定的實作類,隻需要在部署的時候在配置檔案中指定目前采用的實作類即可。

 本例中,為了提高性能,避免每次調用都讀取配置檔案所引起的大量磁盤操作,采用HashMap作為DAO緩存實作示例:

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

public   class  DAOFactory ... {

Factory模式,Proxy模式和持久層

  private static HashMan daoMap=null;

Factory模式,Proxy模式和持久層

  //return a implementation instance of the specified DAO Interface

Factory模式,Proxy模式和持久層

  //return the DAO Implemenation Class Instance

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

  public static Object getDAO(Class daoInterface)...{

Factory模式,Proxy模式和持久層

   initial();

Factory模式,Proxy模式和持久層

   Object dao=doMap.get(daoInterface);

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

   if(null==dao)...{

Factory模式,Proxy模式和持久層

    throw new DAOException ("No Implementation found of DAO inter+daoInterface.getName());

Factory模式,Proxy模式和持久層

   }

Factory模式,Proxy模式和持久層

   return dao;

Factory模式,Proxy模式和持久層

  }

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

  public static synchronized void initial()...{

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

   if(null==daoMap)...{

Factory模式,Proxy模式和持久層

    daoMap=DaoConfig.load();//根據配置檔案中加載DAO實作配置

Factory模式,Proxy模式和持久層

   }

Factory模式,Proxy模式和持久層

  }

Factory模式,Proxy模式和持久層

 }

Factory模式,Proxy模式和持久層

 DAOConfig類實作了配置檔案的讀取功能,并根據配置檔案中的内容加載指定的接口和實作類:

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

public   class  DAOConfig ... {

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

  private static Logger logger=LogManager.getLogger(DAOConfig.class);

Factory模式,Proxy模式和持久層

  private static final String DAO_CONFIG_FILE="dao.xml";

Factory模式,Proxy模式和持久層

  private static final String DAO_CONFIG_SECTION="DAO";

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

  public static synchronized HashMap load()...{

Factory模式,Proxy模式和持久層

   HashMap map=new HashMap();

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

   JFigLocator jfigLocator=new JFigLocator(DAO_CONFIG_FILE);

Factory模式,Proxy模式和持久層

   JFigIF daoConfig=JFig.getInstance(jfigLocator);

Factory模式,Proxy模式和持久層

   Properties prop = daoConfig.getSectionAsProperties(DAO_CONFIG_SECTION);

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

   Enumeration enumSection=prop.keys();

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

   while(enumSection.hashMoreElements())...{

Factory模式,Proxy模式和持久層

    String daoIface = (String)enumSection.nextElement();

Factory模式,Proxy模式和持久層

    String daoImpl=prop.getProperty(daoIface);

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

    try...{

Factory模式,Proxy模式和持久層

     Class iface=ClassToolKit.loadClass(daoIface);

Factory模式,Proxy模式和持久層

     Class impl=ClassToolKit.loadClass(daoImpl);

Factory模式,Proxy模式和持久層

     //将接口作為HashMap索引,實作類作為值

Factory模式,Proxy模式和持久層

     map.put(iface,impl);

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

    }catch(ClassNotFountException e)...{

Factory模式,Proxy模式和持久層

     logger.debug("No Class Found =>"+e);

Factory模式,Proxy模式和持久層

    }

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

   }

Factory模式,Proxy模式和持久層

   return map;

Factory模式,Proxy模式和持久層

  }

Factory模式,Proxy模式和持久層

 }

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

 一個示例配置檔案如下:

Factory模式,Proxy模式和持久層

<? xml version ="1.0" encoding="UTF-8" ?>

Factory模式,Proxy模式和持久層

  < configuration >

Factory模式,Proxy模式和持久層

   < section  name ="DAO" >

Factory模式,Proxy模式和持久層

    < entry  key ="net.xiaxin.lab.persistence.dao.iface.CustormerDAO"

Factory模式,Proxy模式和持久層

    value ="net.xiaxin.lad.persistence.dao.impl.CustomerDAOImpl_Mysql" />

Factory模式,Proxy模式和持久層

    < entry  key ="net.xiaxin.lab.persistence.dao.iface.PromotionDAO"

Factory模式,Proxy模式和持久層

    value ="net.xiaxin.lab.persistence.dao.impl.PromotionDAOImpl_Mysql" />

Factory模式,Proxy模式和持久層

   </ section >

Factory模式,Proxy模式和持久層

  </ configuration >

Factory模式,Proxy模式和持久層

  DAOConfig中使用了JFig讀取XML配置檔案(dao.xml)。關于JFig的具體資訊請參見Http://jfig.sourceforge.net

  ClassToolKit.loadClass方法實作了類檔案的動态加載:

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

public   class  ClassToolKit ... {

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

  public static class loadClass(String className)throws ClassNotFoundException...{

Factory模式,Proxy模式和持久層

   Class cls=null;

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

   try...{

Factory模式,Proxy模式和持久層

    cls=Thread.currentThread().getContextClassLoader().loadClass(className);

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

   }catch(Exception e)...{

Factory模式,Proxy模式和持久層

    e.printStackTrace();

Factory模式,Proxy模式和持久層

   }

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

   if(cls==null)...{

Factory模式,Proxy模式和持久層

    cls=Class.forName(className);

Factory模式,Proxy模式和持久層

   }

Factory模式,Proxy模式和持久層

   return cls;

Factory模式,Proxy模式和持久層

  }

Factory模式,Proxy模式和持久層

 }

Factory模式,Proxy模式和持久層

 經過Factory模式的改造,我們的業務層代碼也進行了相應的改造:

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

public  BigDecimal calcAmount(String custormerID,BigDecimal amount) ... {

Factory模式,Proxy模式和持久層

  CustomerDAO customerDAO=(CustomerDAO)DAOFactory.getDAO(CustomerDAO.class);

Factory模式,Proxy模式和持久層

  Customer customer= customerDAO.getCustomer(customerId);

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

  PromotionDAO promoDAO=(PromotionDAO)DAOFactory.getDAO(PromotionDAO.class);

Factory模式,Proxy模式和持久層

  Promotion promotion=promoDAO.getPromotion(customer.getLevel());

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

  customer.setSumAmount(customer.getSumAmount().add(amount));

Factory模式,Proxy模式和持久層

  customerDAO.save(customer);

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

  return amount.multiply(promotion.getRatio());

Factory模式,Proxy模式和持久層

 }

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

 相對于改造前,這些代碼裡混雜了一些資料通路層的内容,如DAOFactory.getDAO方法的調用

 Proxy模式的作用是通過提供一個中間層(Proxy),将上層調用接口與下層實作相銜接,先看Proxy模式改造的業務層代碼

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

public  BigDecimal calcAmount(String custormerID,BigDecimal amount) ... {

Factory模式,Proxy模式和持久層

  Customer customer= CustomerProxy.getCustomer(customerId);

Factory模式,Proxy模式和持久層

  Promotion promotion=PromotionProxy.getPromotion(customer.getLevel());

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

  customer.setSumAmount(customer.getSumAmount().add(amount));

Factory模式,Proxy模式和持久層

  customerDAO.save(customer);

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

  return amount.multiply(promotion.getRatio());

Factory模式,Proxy模式和持久層

 }

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

 Bad Smell消失了,業務層也清潔了,而CustomerProxy和PromotionProxy做了些什麼呢?

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

  public   class  CustomerProxy ... {

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

  public static Customer getCustomer(String customerID)...{

Factory模式,Proxy模式和持久層

   CustomerDAO custDAO=(CustomerDAO)DAOFactory.getDAO(CustomerDAO.class);

Factory模式,Proxy模式和持久層

   return custDAO.getCustomner(customerID);

Factory模式,Proxy模式和持久層

  }

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

  public static void save(Customer customer)...{

Factory模式,Proxy模式和持久層

   CustomerDAO custDAO=(CustomerDAO)DAOFactory.getDAO(CustomerDAO.class);

Factory模式,Proxy模式和持久層

   custDAO.save(customer);

Factory模式,Proxy模式和持久層

  }

Factory模式,Proxy模式和持久層

 }

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

  public   class  PromotionProxy ... {

Factory模式,Proxy模式和持久層
Factory模式,Proxy模式和持久層

  public static Promotion getPromotion(int level)...{

Factory模式,Proxy模式和持久層

   PromotionDAO promoDAO=(PromotionDAO)DAOFactory.getDAO(PromotionDAO.class);

Factory模式,Proxy模式和持久層

   return promoDAO.getPromotion(level);

Factory模式,Proxy模式和持久層

  }

Factory模式,Proxy模式和持久層

 }  

Factory模式,Proxy模式和持久層

摘自《深入淺出Hibernate》

繼續閱讀