DDD - 如何理解Entity与VO
文章目錄
- 概述
- 狀態(tài)
- 標(biāo)識
- Entity 對比 VO
- 如何識別
概述
為了更好的理解 Entity與VO,我們需要先區(qū)分兩個概念: 狀態(tài) 、 標(biāo)識
狀態(tài)
購物中的訂單狀態(tài),相比大家都熟悉哈 , 比如 發(fā)貨中、 物流派送中、 商品已送達(dá)等等 。 一般訂單狀態(tài)都是使用一個字段來表示的,比如status, status不同的值代表不同的狀態(tài)。
但是這個status就是「訂單狀態(tài)」嗎?難不成狀態(tài)就是一個字段嗎?
我們聯(lián)想一下生活中的例子
- 商品已經(jīng)是發(fā)貨「狀態(tài)」了
- 今天「狀態(tài)」不錯
- …
以 今天「狀態(tài)」不錯 為例,如果狀態(tài)就是一個字段, status=1 狀態(tài)好 status=0 狀態(tài)不好 。感覺不是很合理。
我們會發(fā)現(xiàn),「狀態(tài)」實際上表示的是「目標(biāo)對象在當(dāng)前時刻所呈現(xiàn)出的內(nèi)容」!在系統(tǒng)設(shè)計中中通過一個字段來表示狀態(tài)只是一種簡化手段!
「狀態(tài)」表示的是「當(dāng)前時刻所呈現(xiàn)出的內(nèi)容」, 那么說明了「狀態(tài)」是個快照/瞬態(tài)!也就是說,「目標(biāo)對象」有多個「狀態(tài)」,「當(dāng)前狀態(tài)」只是「目標(biāo)對象」眾多「狀態(tài)」中的一個!
理解了什么是「狀態(tài)」以后,我們就可以來初步區(qū)分Entity和VO了:
-
Entity在整個生命周期中,有多個「狀態(tài)」,也就是說「狀態(tài)」是可變的(至于變不變就看實際情況了)
-
而VO在整個生命周期中,只有一個「狀態(tài)」,也就是說「狀態(tài)」不變
對于VO來說,因為「狀態(tài)」是不可變的,我們就可以用其「狀態(tài)」來表示VO!但是對于Entity來說,因為有多個「狀態(tài)」,且「狀態(tài)」是可變的,那我們?nèi)绾蝸肀硎灸?#xff1f;
舉個例子:假設(shè)同一個買家在同一個賣家那里買了兩個同樣的商品,那兩個訂單里的信息都是一樣的,但是它是兩個不同的訂單,我們?nèi)绾螀^(qū)分這兩個訂單呢?
那就不得不提到 「標(biāo)識 」了
標(biāo)識
說到「標(biāo)識」,最先想到的一般是編程語言中的「引用」或「指針」
Order orderA = new Order("productA",...); Order orderB = new Order("productA",...); orderA.setProductName("productB");orderA和orderB雖然訂單信息(狀態(tài))都相同,但是這是兩個不同的訂單 ,. 即使改了orderA的產(chǎn)品名稱(狀態(tài)),依然還是訂單A。
看似解決了「區(qū)分相同狀態(tài)的不同Entity」的問題,但是沒有解決Entity有多個狀態(tài)的問題。因為「標(biāo)識」指向的是目標(biāo)對象的當(dāng)前狀態(tài)。
語言中的這種「標(biāo)識」就是無法跨系統(tǒng)。比如,在分布式系統(tǒng)中,需要保證兩個系統(tǒng)中的對象是同一個對象,這種「隱式標(biāo)識」是做不到的。
所以「隱式標(biāo)識」并不能滿足我們的需求。我們需要「顯示標(biāo)識」,「顯示標(biāo)識」在現(xiàn)實中很常見:
- 身份證號碼就是每個人的「顯示標(biāo)識」
- 產(chǎn)品編號就是產(chǎn)品的「顯示標(biāo)識」
- …
比如 Order
public Class Order{orderNo // 顯示標(biāo)識productstatus... }設(shè)置訂單號以后,無論訂單的狀態(tài)如何變化,只要訂單號不變,那么它就是同一個訂單。
所以,「標(biāo)識」是另一個區(qū)分Entity和VO的關(guān)鍵點:
- Entity有標(biāo)識
- VO沒有標(biāo)識
注意標(biāo)識并不一定只是一個字段,可能是多個字段的組合,這需要根據(jù)不同的業(yè)務(wù)邏輯來確定。
Entity 對比 VO
-
Entity是具有多個「狀態(tài)」的對象,「狀態(tài)」在其生命周期中可能會改變,通過「標(biāo)識」來唯一確定這個對象
-
VO只有一個「狀態(tài)」,且是在創(chuàng)建時就確定的,也就是說VO是不可變的
那么我們?nèi)绾卧谙到y(tǒng)中識別哪些對象是Entity,哪些對象又是VO呢?
如何識別
一個對象是表示成Entity還是VO,取決于系統(tǒng)的關(guān)注點
舉個例子:
「商品」在「訂單系統(tǒng)」中是個VO,而在「商品管理系統(tǒng)」中是Entity
-
在「商品管理系統(tǒng)」中,系統(tǒng)需要關(guān)注「商品」的「狀態(tài)」,需要維護(hù)是否上架、庫存多少、各種屬性等信息(多種狀態(tài))。就是說在「商品管理系統(tǒng)」中,商品狀態(tài)是可變的。所以它也有「標(biāo)識」,即商品ID
-
「訂單系統(tǒng)」并不關(guān)心「商品」的「狀態(tài)」變化,它只關(guān)注在創(chuàng)建訂單時,這個「商品」的當(dāng)前「狀態(tài)」是什么,并且在訂單創(chuàng)建完成后,這個「商品」的「狀態(tài)」就不會再改變了
在「商品管理系統(tǒng)」中,商品可以這樣表示:
public class Product {id // 商品標(biāo)識namedescstatus... }而在「訂單系統(tǒng)」中,訂單是個Entity,商品是個VO,可以這么表示:
public class Order{orderNo // 訂單標(biāo)識product:Productstatus... }public class Product {id // 這里不是標(biāo)識,只是狀態(tài)namedescstatus... }注意這里的id并不是標(biāo)識,這里的id實際上退化成了狀態(tài)的一部分,保留這個id是為了和「商品管理系統(tǒng)」進(jìn)行交互,通過id從商品管理系統(tǒng)中查詢商品。當(dāng)然還有其它方式,例如保存「商品管理系統(tǒng)」中該商品的歷史URL。
總結(jié)
以上是生活随笔為你收集整理的DDD - 如何理解Entity与VO的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java Review - 使用Even
- 下一篇: DDD - 聚合与聚合根_如何理解 Re