Factory模式,Proxy模式和持久层

 作为最常用的创建模式,Factory模式在这里起到连接接口和实现的桥梁作用。通过Factory模式,我们可以根据具体需要加载相应的实现,并将此
实现作为所对应接口的一个实例提供给业务层使用:

CustomerDao custDAO = (CustomerDAO)DAOFactory.getDAO(CustomerDAO. class );
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 interface=>"+daoInterface.getName());
   }

   
return dao;
  }

  
/**
   *Initial the DAOFactory
   *Load DAO Interface and Implementation In daoMap for later use
   
*/

  
public static synchronized void initial(){
   
if(null==daoMap){
    daoMap
=DaoConfig.load();//根据配置文件中加载DAO实现配置
   }

  }

 }

 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";
  
/**
   * Load the DAO Interface_Implementation into a HashMap
   * @return
   
*/

  
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;
  }

 }


 一个示例配置文件如下:
 

<? xml version ="1.0" encoding="UTF-8" ?>
 
< configuration >
  
< section  name ="DAO" >
   
< entry  key ="net.xiaxin.lab.persistence.dao.iface.CustormerDAO"
    value
="net.xiaxin.lad.persistence.dao.impl.CustomerDAOImpl_Mysql" />
   
< entry  key ="net.xiaxin.lab.persistence.dao.iface.PromotionDAO"
    value
="net.xiaxin.lab.persistence.dao.impl.PromotionDAOImpl_Mysql" />
  
</ section >
 
</ configuration >

  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;
  }

 }

 经过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());
 }


 相对于改造前,这些代码里混杂了一些数据访问层的内容,如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());
 }


 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);
  }

 }


 
public   class  PromotionProxy {
  
public static Promotion getPromotion(int level){
   PromotionDAO promoDAO
=(PromotionDAO)DAOFactory.getDAO(PromotionDAO.class);
   
return promoDAO.getPromotion(level);
  }

 }
 

摘自《深入浅出Hibernate》

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值