posts - 66,  comments - 11,  trackbacks - 0
    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 王永庆 阅读(150) 评论(0)  编辑  收藏 所属分类: HIBERNATE

只有注册用户登录后才能发表评论。


网站导航:
 
<2009年10月>
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567

常用链接

留言簿(1)

随笔分类

随笔档案

关注blogs

搜索

  •  

最新评论

阅读排行榜

评论排行榜