论坛首页 Java企业应用论坛

我的酒窝

浏览 43497 次
锁定老帖子 主题:我的酒窝
该帖已经被评为精华帖
作者 正文
   发表时间:2007-01-08  
codehaus上的用dimple进行ibatis integration的介绍
http://dimple.codehaus.org/Integrate+IBatis+With+Legacy+System
0 请登录后投票
   发表时间:2007-01-11  
继续给酒窝寻找用途。

在robbin的domain model设计的帖子中,提到了第二种模型(rich domain model)的一些不足之处(贫血模型也有一样的毛病)。引用如下:
引用

问题就在于这个充当business workflow facade的业务逻辑对象,它的变动是相当频繁的。业务逻辑对象通常都是无状态的、受事务控制的、Singleton类,我们可以考察一下业务逻辑对象都有哪几类业务逻辑方法:

第一类:DAO接口方法的代理,就是上面例子中的loadItemById方法和findAll方法。

ItemManager之所以要代理这种类,目的有两个:向Web层提供统一的服务调用入口点和给持久化方法增加事务控制功能。这两点都很容易理解,你不能既给Web层程序员提供xxxManager,也给他提供xxxDao,所以你需要用xxxManager封装xxxDao,在这里,充当了一个简单代理功能;而事务控制也是持久化方法必须的,事务可能需要跨越多个DAO方法调用,所以必须放在业务逻辑层,而不能放在DAO层。

但是必须看到,对于一个典型的web应用来说,绝大多数的业务逻辑都是简单的CRUD逻辑,所以这种情况下,针对每个DAO方法,xxxManager都需要提供一个对应的封装方法,这不但是非常枯燥的,也是令人感觉非常不好的。

第二类:domain logic的方法代理。就是上面例子中placeBid方法。虽然Item已经有了placeBid方法,但是ItemManager仍然需要封装一下Item的placeBid,然后再提供一个简单封装之后的代理方法。

这和第一种情况类似,其原因也一样,也是为了给Web层提供一个统一的服务调用入口点和给隐式的持久化动作提供事务控制。

同样,和第一种情况一样,针对每个domain logic方法,xxxManager都需要提供一个对应的封装方法,同样是枯燥的,令人不爽的。

第三类:需要多个domain object和DAO参与协作的business workflow。这种情况是业务逻辑对象真正应该完成的职责。

在这个简单的例子中,没有涉及到这种情况,不过大家都可以想像的出来这种应用场景,因此不必举例说明了。

通过上面的分析可以看出,只有第三类业务逻辑方法才是业务逻辑对象真正应该承担的职责,而前两类业务逻辑方法都是“无奈之举”,不得不为之的事情,不但枯燥,而且令人沮丧。


原文见:http://www.iteye.com/topic/11712

引用的这段话主要是说,在下面这个代码中,ItemManager必须要对loadItemById(), findAll()这两个方法进行委托:
public interface ItemDao {  
  public Item getItemById(Long id);  
  public Collection findAll();  
  public void updateItem(Item item);  
}  
public class ItemManager { 
    private ItemDao itemDao; 
    public void setItemDao(ItemDao itemDao) { this.itemDao = itemDao;} 
    public Bid loadItemById(Long id) { 
        itemDao.loadItemById(id); 
    } 
    public Collection listAllItems() { 
        return  itemDao.findAll(); 
    } 
    public Bid placeBid(Item item, User bidder, MonetaryAmount bidAmount, 
                            Bid currentMaxBid, Bid currentMinBid) throws BusinessException { 
        item.placeBid(bidder, bidAmount, currentMaxBid, currentMinBid);
        itemDao.update(item);    // 必须显式的调用DAO,保持持久化
    }
}  

例子中只有两个方法,还没什么,但是如果有10个呢?100个呢?这个委托就烦死人了。

我无意在此继续炒哪种domain model更好,我要做的,只是show一下酒窝可以用来解决robbin提出的这个问题的。

怎么解决呢,很简单,只要保证ItemManager里面的方法和被委托的方法签名一致就好了。最容易达到这个目的的办法就是弄一个额外的package private interface出来。这个接口的唯一目的是让ItemDao和ItemManager共同继承一些签名:
interface AboutItem {  
  Item getItemById(Long id);  
  Collection findAll();
}

然后,让ItemDao继承AboutItem,再给ItemManager提取出一个接口出来:
public interface ItemDao extends AboutItem {
  void updateItem(Item item);  
}
public interface ItemManager extends AboutItem {
  Bid placeBid(Item item, User bidder, MonetaryAmount bidAmount, 
                            Bid currentMaxBid, Bid currentMinBid) throws BusinessException;
}

到此为止呢,仅仅是声明一些接口,没有任何实现上的动作。
下面用dimple来实现ItemManagerImpl对ItemDao的委托:
public class ItemManagerImpl { 
    private ItemDao itemDao; 
    public Bid placeBid(Item item, User bidder, MonetaryAmount bidAmount, 
                            Bid currentMaxBid, Bid currentMinBid) throws BusinessException { 
        item.placeBid(bidder, bidAmount, currentMaxBid, currentMinBid);
        itemDao.update(item);    // 必须显式的调用DAO,保持持久化
    }
}
ItemDao dao = ...;
ItemManagerImpl impl = ...;
ItemManager manager = (ItemManager)Implementor.proxy(ItemManager.class, impl, itemDao);

这样,robbin提出的被迫写很多委托的问题就不存在了。也就不令人沮丧了。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics