DAO:::::DAO實現對數據庫的操作.
SERVICE::::::Service實現業務邏輯的封裝,數據庫操作只是業務邏輯的一部分而已。
但是在實際應用中,建議使用Service+DAO,看似麻煩些,但分層能相對清晰一點。
總之,我還是很喜歡把DAO和SERVICE分開的。這樣起碼以後容易擴展並且看起來邏輯清晰.
看過的一篇帖子說:比如現在用hibernate 以後可能改爲jdbc或者其他的也比較方便,SERVICE是單純的進行業務邏輯處理調用DAO來持久數據,所以DAO和SERVICE還是應該要獨立的!
以下是我看到的一個帖子,總結的很好。做爲收藏.....
第二種模型,也就是Martin Fowler指的rich domain object是下面這樣子的:
一個帶有業務邏輯的實體類,即domain object是Item
一個DAO接口ItemDao
一個DAO實現ItemDaoHibernateImpl
一個業務邏輯對象ItemManager
java 代碼
- public
class Item
implements Serializable {
-
- public Bid placeBid(User bidder, MonetaryAmount bidAmount,
- Bid currentMaxBid, Bid currentMinBid)
- throws BusinessException {
-
-
- if (currentMaxBid !=
null && currentMaxBid.getAmount().compareTo(bidAmount) >
0) {
- throw
new BusinessException("Bid too low.");
- }
-
-
- if ( !state.equals(ItemState.ACTIVE) )
- throw
new BusinessException("Auction is not active yet.");
-
-
- if (
this.getEndDate().before(
new Date() ) )
- throw
new BusinessException("Can't place new bid, auction already ended.");
-
-
- Bid newBid = new Bid(bidAmount,
this, bidder);
-
-
- this.getBids.add(newBid);
-
- return newBid;
- }
- }
<script>render_code();</script>
競標這個業務邏輯被放入到Item中來。請注意this.getBids.add(newBid); 如果沒有Hibernate或者JDO這種O/R Mapping的支持,我們是無法實現這種透明的持久化行爲的。但是請注意,Item裏面不能去調用ItemDAO,對ItemDAO產生依賴!
java 代碼
- public
interface ItemDao {
- public Item getItemById(Long id);
- public Collection findAll();
- public
void updateItem(Item item);
- }
ItemDao定義持久化操作的接口,用於隔離持久化代碼。
java 代碼
- public
class ItemDaoHibernateImpl
implements ItemDao
extends HibernateDaoSupport {
- public Item getItemById(Long id) {
- return (Item) getHibernateTemplate().load(Item.class,
id);
- }
- public Collection findAll() {
- return (List) getHibernateTemplate().find("from Item");
- }
- public
void updateItem(Item item) {
- getHibernateTemplate().update(item);
- }
- }
java 代碼
- 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);
- }
- }
<script>render_code();</script>
在第二種模型中,placeBid業務邏輯是放在Item中實現的,而loadItemById和findAll業務邏輯是放在ItemManager中實現的。不過值得注意的是,即使placeBid業務邏輯放在Item中,你仍然需要在ItemManager中簡單的封裝一層,以保證對placeBid業務邏輯進行事務的管理和持久化的觸發。
這種模型是Martin Fowler所指的真正的domain model。在這種模型中,有三個業務邏輯方法:placeBid,loadItemById和findAll,現在的問題是哪個邏輯應該放在Item中,哪個邏輯應該放在ItemManager中。在我們這個例子中,placeBid放在Item中(但是ItemManager也需要對它進行簡單的封裝),loadItemById和findAll是放在ItemManager中的。
切分的原則是什麼呢? Rod Johnson提出原則是“case by case”,可重用度高的,和domain object狀態密切關聯的放在Item中,可重用度低的,和domain object狀態沒有密切關聯的放在ItemManager中。
我提出的原則是:看業務方法是否顯式的依賴持久化。
Item的placeBid這個業務邏輯方法沒有顯式的對持久化ItemDao接口產生依賴,所以要放在Item中。請注意,如果脫離了Hibernate這個持久化框架,Item這個domain object是可以進行單元測試的,他不依賴於Hibernate的持久化機制。它是一個獨立的,可移植的,完整的,自包含的域對象。
而loadItemById和findAll這兩個業務邏輯方法是必須顯式的對持久化ItemDao接口產生依賴,否則這個業務邏輯就無法完成。如果你要把這兩個方法放在Item中,那麼Item就無法脫離Hibernate框架,無法在Hibernate框架之外獨立存在。