Kira-2006
-仅仅是一阵风也罢了,偏偏是这样永恒, 仅仅是一场梦也罢了,偏偏是如此的真实,
posts - 4,comments - 7,trackbacks - 0
解耦合的设计目标:
    1. 应用层解耦合--应用逻辑与数据逻辑相分离。
    2. 资源层解耦合--逻辑结构与物理结构相分离。

DAO模式:即Data Accessor模式和Active Domain Object模式。
    Data Accessor模式:实现数据访问和业务逻辑的分离。
    Active Domain Object:实现了业务数据的对象化封装。
    Domain Object:简单来讲就是对领域内涉及的各个数据对象,反映到代码,就是一个拥有相关属性的getter,setter方法的java Bean。

    DAO模式通过对业务逻辑蹭提供数据抽象层接口,实现了以下目标:
        
1. 数据存储逻辑的分离:通过对数据访问逻辑进行抽象,为上层结构提供抽象化的数据访问接口。
        2. 数据访问底层实现的分离:数据访问划分为抽象层和实现层,从而分离了数据使用和数据访问的底层实现细节。
        3. 资源管理和调用的分离。
        4.数据抽象:DAO模式通过对底层数据的封装,为业务层提供了一个面向对象的接口,使得业务逻辑开发人员可以面向业务中的实体进行编程。
        DAO = Data+Accessor+Domain Object

DAO模式的进一步改良
    Factory模式的引入:
        由于需要针对不同的数据库访问机制分别提供各个版本的Data Accessor实现,自然我们会想到通过java interface定义一个调用接口,然后针对这个调用接口实现不同数据库的Data Accessor。通过接口作为调用界面和实现规范,可以避免对具体实现的依赖。
        
public interface CustomerDAO{
    
public Customer getCustomer(String custID);
    
public void save(Customer customer);
}

作为最常见的创建模式,Factory模式在这里起到连接接口和实现的桥梁作用,通过Factory模式,我们可以根据具体的需要加载相应的实现,并将此实现作为所对应接口的一个实例提供给业务层使用。
CustomerDAO custDAO = (CustomerDAO)DAOFactory.getDAO(CustomerDAO.class);
Customer customer 
= custDAO.getCustomer(custoemrID);
业务逻辑层通过接口调用底层实现,具体的DAO实现类不会出现在我们的业务代码中。而具体实现类在配置文件中加以配置,之后DAOFactory.getDAO方法通过读取配置文件获得当前我们期望使用的实现类的类名,再通过java Class动态加载机制加载返回。
从而我们的代码不依赖于某个特定的实现类,只需要在部署的时候在配置文件中指定当前采用的实现类即可。
public class DAOFactory{
    
private static HashMap daoMap = null;

    
//根据指定的Class来获取DAO实例
    public static Object getDAO(Class daoInterface){
        initial();
        Object dao
=daoMap.get(daoInterface);
        
if(null==dao){
            
throw new DAOException("No implementation found of DAO interface => "+daoInterface.getName());
        }

        
return dao;
    }


    
//初始化DAOFactory,加载DAO interface和 
    
//implementation到daoMap中
    public static sychronized void initial(){
        
if(null==daoMap){
            
//根据配置文件中加载DAO实现配置
            daoMap = DAOConfig.load();
        }

    }

}


//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 
= JFig.getInstance(jfigLocator);
        Properties prop
=daoConfig.getSectionAsProperties(DAO_CONFIG_SECTION);
        Enumeration enumSection
=prop.Keys();
        
while(enumSection.hasMoreElements()){
            String daoIface
=(String)enumSectioni.nextElement();
            String daoImpl
=(String)prop.getProperty(daoIface);
            
try{
                Class iface
=ClassToolKit.loadClass(daoIface);
                Class impl
=ClassToolKit.loadClass(daoImpl);
                
//将接口作为索引,实现作为值。
                map.put(iface,impl);
            }
catch(ClassNotFoundException e){
                logger.debug(
"No Class Found => "+e);
             }

        }

        
return map;
    }

}

ClassToolKit.loadClass方法实现了类文件的动态加载:
public class ClassToolKit{
    
public static Class loadClass(String className)throws ClassNotFoundException{
        Class cls
=null;
        
try{
            
//首先尝试用当前ClassLoader加载
            cls=Thread.currentThread().getContextClassLoader().loadClass(className);
        }
catch(Exception e){
            e.printStackTrace();
        }

        
if(cls==null){
            
//如果通过当前ClassLoader加载失败,使
              
//用系统ClassLoader加载
            cls=Class.forName(className);
        }

        
return cls;
    }

}
这样,通过接口与实现的分离,并结合DAOFactory动态加载实现类,我们就实现了底层访问实现的参数化配置功能。从而为增强产品的部署能力提供了强有力的支持。
    经过Factory模式的改造,业务层代码进行相应的修改:
public BigDecimal calcAmount(String customerID,BigDecimal amount){
    
//根据客户ID获得客户记录
    CustomerDAO customerDAO=(CustomerDAO)DAOFactory.getDAO(CustomerDAO.class);
    Customercustomer
=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模式的引入
    为了保持业务逻辑代码的简洁,将Factory模式带来的Bad Smell排除在系统外,引入Proxy模式。
    Proxy模式的作用:通过提供一个中间层(Proxy),将上层调用接口与下层实现相衔接。
    经过Proxy模式改进后的业务层代码:
public BigDecimal calcAmount(String customerID,BigDecimal amount){
    Customer customer
=CustomerProxy.getCustomer(customerID);

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

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

    CustomerProxy.save(customer);

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

}

public class CustomerProxy{
    
//get Customer Object by CustomerID
    public static Customer getCustomer(String customerID){
        customerDAO custDAO
=(CustomerDAO)DAOFactory.getDAO(CustomerDAO.class);
        
return custDAO.getCustomer(customerID);
    }


    
//Save Customer Object to DataBase
    public static void save(Customer customer){
        CustomerDAO custDAO
=(CUstomerDAO)DAOFactory.getDAO(CustomerDAO.class);
        custDAO.save(customer);
    }

}

posted on 2008-05-02 19:33 Kira-2006 阅读(392) 评论(0)  编辑  收藏 所属分类: hibernate

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


网站导航: