国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
總結(jié)一下最近關(guān)于domain object以及相關(guān)的討論

時間: 2005-3-24 16:48:06    標(biāo)題: 總結(jié)一下最近關(guān)于domain object以及相關(guān)的討論
 

在最近的圍繞domain object的討論中浮現(xiàn)出來了三種模型,(還有一些其他的旁枝,不一一分析了),經(jīng)過一番討論,各種問題逐漸清晰起來,在這里我試圖做一個總結(jié),便于大家了解和掌握。 

第一種模型:只有g(shù)etter/setter方法的純數(shù)據(jù)類,所有的業(yè)務(wù)邏輯完全由business object來完成(又稱TransactionScript),這種模型下的domain object被Martin Fowler稱之為“貧血的domain object”。下面用舉一個具體的代碼來說明,代碼來自Hibernate的caveatemptor,但經(jīng)過我的改寫: 

一個實體類叫做Item,指的是一個拍賣項目 
一個DAO接口類叫做ItemDao 
一個DAO接口實現(xiàn)類叫做ItemDaoHibernateImpl 
一個業(yè)務(wù)邏輯類叫做ItemManager(或者叫做ItemService) 

java代碼: 

public class Item implements Serializable { 
    private Long id = null; 
    private int version; 
    private String name; 
    private User seller; 
    private String description; 
    private MonetaryAmount initialPrice; 
    private MonetaryAmount reservePrice; 
    private Date startDate; 
    private Date endDate; 
    private Set categorizedItems = new HashSet(); 
    private Collection bids = new ArrayList(); 
    private Bid successfulBid; 
    private ItemState state; 
    private User approvedBy; 
    private Date approvalDatetime; 
    private Date created = new Date(); 
    //  getter/setter方法省略不寫,避免篇幅太長 
}



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


ItemDaoHibernateImpl完成具體的持久化工作,請注意,數(shù)據(jù)庫資源的獲取和釋放是在ItemDaoHibernateImpl里面處理的,每個DAO方法調(diào)用之前打開Session,DAO方法調(diào)用之后,關(guān)閉Session。(Session放在ThreadLocal中,保證一次調(diào)用只打開關(guān)閉一次) 

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 { 
            if (currentMaxBid != null && currentMaxBid.getAmount().compareTo(bidAmount) > 0) { 
            throw new BusinessException("Bid too low."); 
    } 
    
    // Auction is active 
    if ( !state.equals(ItemState.ACTIVE) ) 
            throw new BusinessException("Auction is not active yet."); 
    
    // Auction still valid 
    if ( item.getEndDate().before( new Date() ) ) 
            throw new BusinessException("Can‘t place new bid, auction already ended."); 
    
    // Create new Bid 
    Bid newBid = new Bid(bidAmount, item, bidder); 
    
    // Place bid for this Item 
    item.getBids().add(newBid); 
    itemDao.update(item);     //  調(diào)用DAO完成持久化操作 
    return newBid; 
    } 
}



事務(wù)的管理是在ItemManger這一層完成的,ItemManager實現(xiàn)具體的業(yè)務(wù)邏輯。除了常見的和CRUD有關(guān)的簡單邏輯之外,這里還有一個placeBid的邏輯,即項目的競標(biāo)。 

以上是一個完整的第一種模型的示例代碼。在這個示例中,placeBid,loadItemById,findAll等等業(yè)務(wù)邏輯統(tǒng)統(tǒng)放在ItemManager中實現(xiàn),而Item只有g(shù)etter/setter方法。


上一次由robbin于2005-3-24 周四, 下午5:38修改,總共修改了1次




第二種模型,也就是Martin Fowler指的rich domain object是下面這樣子的: 

一個帶有業(yè)務(wù)邏輯的實體類,即domain object是Item 
一個DAO接口ItemDao 
一個DAO實現(xiàn)ItemDaoHibernateImpl 
一個業(yè)務(wù)邏輯對象ItemManager 

java代碼: 

public class Item implements Serializable { 
    //  所有的屬性和getter/setter方法同上,省略 
    public Bid placeBid(User bidder, MonetaryAmount bidAmount, 
                        Bid currentMaxBid, Bid currentMinBid) 
            throws BusinessException { 
    
            // Check highest bid (can also be a different Strategy (pattern)) 
            if (currentMaxBid != null && currentMaxBid.getAmount().compareTo(bidAmount) > 0) { 
                    throw new BusinessException("Bid too low."); 
            } 
    
            // Auction is active 
            if ( !state.equals(ItemState.ACTIVE) ) 
                    throw new BusinessException("Auction is not active yet."); 
    
            // Auction still valid 
            if ( this.getEndDate().before( new Date() ) ) 
                    throw new BusinessException("Can‘t place new bid, auction already ended."); 
    
            // Create new Bid 
            Bid newBid = new Bid(bidAmount, this, bidder); 
    
            // Place bid for this Item 
            this.getBids.add(newBid);  // 請注意這一句,透明的進(jìn)行了持久化,但是不能在這里調(diào)用ItemDao,Item不能對ItemDao產(chǎn)生依賴! 
    
            return newBid; 
    } 
}



競標(biāo)這個業(yè)務(wù)邏輯被放入到Item中來。請注意this.getBids.add(newBid); 如果沒有Hibernate或者JDO這種O/R Mapping的支持,我們是無法實現(xiàn)這種透明的持久化行為的。但是請注意,Item里面不能去調(diào)用ItemDAO,對ItemDAO產(chǎn)生依賴! 

ItemDao和ItemDaoHibernateImpl的代碼同上,省略。 

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);    // 必須顯式的調(diào)用DAO,保持持久化 
    } 
}



在第二種模型中,placeBid業(yè)務(wù)邏輯是放在Item中實現(xiàn)的,而loadItemById和findAll業(yè)務(wù)邏輯是放在ItemManager中實現(xiàn)的。不過值得注意的是,即使placeBid業(yè)務(wù)邏輯放在Item中,你仍然需要在ItemManager中簡單的封裝一層,以保證對placeBid業(yè)務(wù)邏輯進(jìn)行事務(wù)的管理和持久化的觸發(fā)。 

這種模型是Martin Fowler所指的真正的domain model。在這種模型中,有三個業(yè)務(wù)邏輯方法:placeBid,loadItemById和findAll,現(xiàn)在的問題是哪個邏輯應(yīng)該放在Item中,哪個邏輯應(yīng)該放在ItemManager中。在我們這個例子中,placeBid放在Item中(但是ItemManager也需要對它進(jìn)行簡單的封裝),loadItemById和findAll是放在ItemManager中的。 

切分的原則是什么呢? Rod Johnson提出原則是“case by case”,可重用度高的,和domain object狀態(tài)密切關(guān)聯(lián)的放在Item中,可重用度低的,和domain object狀態(tài)沒有密切關(guān)聯(lián)的放在ItemManager中。 

我提出的原則是:看業(yè)務(wù)方法是否顯式的依賴持久化。 

Item的placeBid這個業(yè)務(wù)邏輯方法沒有顯式的對持久化ItemDao接口產(chǎn)生依賴,所以要放在Item中。請注意,如果脫離了Hibernate這個持久化框架,Item這個domain object是可以進(jìn)行單元測試的,他不依賴于Hibernate的持久化機(jī)制。它是一個獨立的,可移植的,完整的,自包含的域?qū)ο?/span>。 

而loadItemById和findAll這兩個業(yè)務(wù)邏輯方法是必須顯式的對持久化ItemDao接口產(chǎn)生依賴,否則這個業(yè)務(wù)邏輯就無法完成。如果你要把這兩個方法放在Item中,那么Item就無法脫離Hibernate框架,無法在Hibernate框架之外獨立存在。




第三種模型印象中好像是firebody或者是Archie提出的(也有可能不是,記不清楚了),簡單的來說,這種模型就是把第二種模型的domain object和business object合二為一了。所以ItemManager就不需要了,在這種模型下面,只有三個類,他們分別是: 

Item:包含了實體類信息,也包含了所有的業(yè)務(wù)邏輯 
ItemDao:持久化DAO接口類 
ItemDaoHibernateImpl:DAO接口的實現(xiàn)類 

由于ItemDao和ItemDaoHibernateImpl和上面完全相同,就省略了。 

java代碼: 

public class Item implements Serializable { 
    //  所有的屬性和getter/setter方法都省略 
   private static ItemDao itemDao; 
    public void setItemDao(ItemDao itemDao) {this.itemDao = itemDao;} 
    
    public static Item loadItemById(Long id) { 
        return (Item) itemDao.loadItemById(id); 
    } 
    public static Collection findAll() { 
        return (List) itemDao.findAll(); 
    } 

    public Bid placeBid(User bidder, MonetaryAmount bidAmount, 
                    Bid currentMaxBid, Bid currentMinBid) 
    throws BusinessException { 
    
        // Check highest bid (can also be a different Strategy (pattern)) 
        if (currentMaxBid != null && currentMaxBid.getAmount().compareTo(bidAmount) > 0) { 
                throw new BusinessException("Bid too low."); 
        } 
        
        // Auction is active 
        if ( !state.equals(ItemState.ACTIVE) ) 
                throw new BusinessException("Auction is not active yet."); 
        
        // Auction still valid 
        if ( this.getEndDate().before( new Date() ) ) 
                throw new BusinessException("Can‘t place new bid, auction already ended."); 
        
        // Create new Bid 
        Bid newBid = new Bid(bidAmount, this, bidder); 
        
        // Place bid for this Item 
        this.addBid(newBid); 
        itemDao.update(this);      //  調(diào)用DAO進(jìn)行顯式持久化 
        return newBid; 
    } 
}



在這種模型中,所有的業(yè)務(wù)邏輯全部都在Item中,事務(wù)管理也在Item中實現(xiàn)。




robbin 寫道:
第三種模型印象中好像是firebody或者是Archie提出的(也有可能不是,記不清楚了),簡單的來說,這種模型就是把第二種模型的domain object和business object合二為一了。所以ItemManager就不需要了,在這種模型下面,只有三個類,他們分別是: 

Item:包含了實體類信息,也包含了所有的業(yè)務(wù)邏輯 
ItemDao:持久化DAO接口類 
ItemDaoHibernateImpl:DAO接口的實現(xiàn)類 

由于ItemDao和ItemDaoHibernateImpl和上面完全相同,就省略了。 

java代碼: 

public class Item implements Serializable { 
    //  所有的屬性和getter/setter方法都省略 
   private static ItemDao itemDao; 
    public void setItemDao(ItemDao itemDao) {this.itemDao = itemDao;} 
    
    public static Item loadItemById(Long id) { 
        return (Item) itemDao.loadItemById(id); 
    } 
    public static Collection findAll() { 
        return (List) itemDao.findAll(); 
    } 

    public Bid placeBid(User bidder, MonetaryAmount bidAmount, 
                    Bid currentMaxBid, Bid currentMinBid) 
    throws BusinessException { 
    
        // Check highest bid (can also be a different Strategy (pattern)) 
        if (currentMaxBid != null && currentMaxBid.getAmount().compareTo(bidAmount) > 0) { 
                throw new BusinessException("Bid too low."); 
        } 
        
        // Auction is active 
        if ( !state.equals(ItemState.ACTIVE) ) 
                throw new BusinessException("Auction is not active yet."); 
        
        // Auction still valid 
        if ( this.getEndDate().before( new Date() ) ) 
                throw new BusinessException("Can‘t place new bid, auction already ended."); 
        
        // Create new Bid 
        Bid newBid = new Bid(bidAmount, this, bidder); 
        
        // Place bid for this Item 
        this.addBid(newBid); 
        itemDao.update(this);      //  調(diào)用DAO進(jìn)行顯式持久化 
        return newBid; 
    } 
}



在這種模型中,所有的業(yè)務(wù)邏輯全部都在Item中,事務(wù)管理也在Item中實現(xiàn)。


這個我想解釋一下,也存在一些疑問。 

1.事務(wù)我是不希望由Item管理的,而是由容器或更高一層的業(yè)務(wù)類來管理。 

2.如果Item不脫離持久層的管理,如JDO的pm,那么itemDao.update(this); 是不需要的,也就是說Item是在事務(wù)過程中從數(shù)據(jù)庫拿出來的,并且聲明周期不超出當(dāng)前事務(wù)的范圍。 

3.如果Item是脫離持久層,也就是在Item的生命周期超出了事務(wù)的范圍,那就要必須顯示調(diào)用update或attach之類的持久化方法的,這種時候就應(yīng)該是按robbin所說的第2種模型來做。 

PS:書已到手,連夜苦讀,希望能看出什么門道來。





在上面三種模型之外,還有很多這三種模型的變種,例如partech的模型就是把第二種模型中的DAO和Manager三個類合并為一個類后形成的模型;例如frain....(id很長記不住)的模型就是把第三種模型的三個類完全合并為一個單類后形成的模型;例如Archie是把第三種模型的Item又分出來一些純數(shù)據(jù)類(可能是,不確定)形成的一個模型。 

但是不管怎么變,基本模型歸納起來就是上面的三種模型,下面分別簡單評價一下: 

第一種模型絕大多數(shù)人都反對,因此反對理由我也不多講了。但遺憾的是,我觀察到的實際情形是,很多使用Hibernate的公司最后都是這種模型,這里面有很大的原因是很多公司的技術(shù)水平?jīng)]有達(dá)到這種層次,所以導(dǎo)致了這種貧血模型的出現(xiàn)。從這一點來說,Martin Fowler的批評聲音不是太響了,而是太弱了,還需要再繼續(xù)吶喊。 

第二種模型就是Martin Fowler一直主張的模型,實際上也是我一直在實際項目中采用這種模型。我沒有看過Martin的POEAA,之所以能夠自己摸索到這種模型,也是因為從02年我已經(jīng)開始思考這個問題并且尋求解決方案了,但是當(dāng)時沒有看到Hibernate,那時候做的一個小型項目我已經(jīng)按照這種模型來做了,但是由于沒有O/R Mapping的支持,寫到后來又不得不全部改成貧血的domain object,項目做完以后再繼續(xù)找,隨后就發(fā)現(xiàn)了Hibernate。當(dāng)然,現(xiàn)在很多人一開始就是用Hibernate做項目,沒有經(jīng)歷過我經(jīng)歷的那個階段。 

不過我覺得這種模型仍然不夠完美,因為你還是需要一個業(yè)務(wù)邏輯層來封裝所有的domain logic,這顯得非常羅嗦,并且業(yè)務(wù)邏輯對象的接口也不夠穩(wěn)定。如果不考慮業(yè)務(wù)邏輯對象的重用性的話(業(yè)務(wù)邏輯對象的可重用性也不可能好),很多人干脆就去掉了xxxManager這一層,在Web層的Action代碼直接調(diào)用xxxDao,同時容器事務(wù)管理配置到Action這一層上來。Hibernate的caveatemptor就是這樣架構(gòu)的一個典型應(yīng)用。 

第三種模型是我很反對的一種模型,這種模型下面,Domain Object和DAO形成了雙向依賴關(guān)系,無法脫離框架測試,并且業(yè)務(wù)邏輯層的服務(wù)也和持久層對象的狀態(tài)耦合到了一起,會造成程序的高度的復(fù)雜性,很差的靈活性和糟糕的可維護(hù)性。也許將來技術(shù)進(jìn)步導(dǎo)致的O/R Mapping管理下的domain object發(fā)展到足夠的動態(tài)持久透明化的話,這種模型才會成為一個理想的選擇。就像O/R Mapping的流行使得第二種模型成為了可能(O/R Mapping流行以前,我們只能用第一種模型,第二種模型那時候是不現(xiàn)實的)。
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
DAO與SERVICE
基于Spring實現(xiàn)領(lǐng)域模型模式 - RUP實踐者指南 - JavaEye技術(shù)網(wǎng)站
基于struts+spring+ibatis的輕量級J2EE開發(fā)
DAO-持久層-領(lǐng)域?qū)ο?貧血模型
Generic Data Access Objects
使用Spring MVC統(tǒng)一異常處理實戰(zhàn)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服