日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
如何選擇充血模型和貧血模型

從領(lǐng)域模型說起

  1. 進(jìn)行需求分析
  2. 進(jìn)行用例設(shè)計
  3. 針對用例進(jìn)行領(lǐng)域建模
  4. 針對領(lǐng)域模型并行進(jìn)行數(shù)據(jù)庫設(shè)計和程序設(shè)計。

在經(jīng)過了前面幾步分析后,我們會得到領(lǐng)域模型以及他們之間的關(guān)系。在這之后我們要根據(jù)領(lǐng)域模型分別進(jìn)行數(shù)據(jù)庫設(shè)計與程序設(shè)計。我們會根據(jù)領(lǐng)域模型之間的關(guān)系將模型之間的關(guān)系映射到系統(tǒng)表設(shè)計之間的關(guān)系。那么我們該怎么進(jìn)行對應(yīng)的程序設(shè)計呢?

一般來說:

將領(lǐng)域模型設(shè)計轉(zhuǎn)化為程序設(shè)計,有貧血模型與充血模型兩種方法。

貧血模型

在之前的文章中我們舉過一個訂單模型的例子:

在這個例子中我們經(jīng)過了設(shè)計和抽象得到了一個訂單模型。而根據(jù)這個模型,我們可以直接將模型中的屬性抽離成為一個模型設(shè)計,將模型中的方法能力抽取為一個服務(wù)設(shè)計。也就是說:

只由屬性及其賦值器、取值器構(gòu)成的對象,我們稱之為貧血模型。

那么如果使用貧血模型進(jìn)行領(lǐng)域模型的程序設(shè)計,就會像上圖中的例子一樣,得到一個領(lǐng)域模型的實體對象與服務(wù)。實體對象將包含模型對象的所有屬性與數(shù)據(jù),服務(wù)中包含領(lǐng)域模型中的所有方法。當(dāng)我們希望使用領(lǐng)域模型中的方法時,是將模型實體作為參數(shù)調(diào)用服務(wù)中領(lǐng)域模型對應(yīng)的方法。

在利用貧血模型建模后,原有的領(lǐng)域模型中的數(shù)據(jù)與方法被割裂到了兩個對象中。而這種割裂使得原本被封裝到一個對象中的內(nèi)容,被分開到了兩個對象中。而打破了原本領(lǐng)域模型的封裝性。

封裝性的打破會帶來新的問題,我舉一個我在實際生產(chǎn)中遇到過的例子:

如圖所示,如果對于訂單來說我們出現(xiàn)了兩種子對象:入駐商家訂單、自營訂單。對于這兩種訂單的下單方法中是有不一樣的業(yè)務(wù)流程的。如果使用貧血模型設(shè)計的話,我們很容易就想到將兩個不一樣的下單業(yè)務(wù)流程分別通過兩個服務(wù)來實現(xiàn)。那么對應(yīng)的,為了區(qū)分服務(wù)的不同,就需要將訂單也分別分割為兩個對象,并且指定的對象作為入?yún)⒄{(diào)用對應(yīng)的服務(wù)。

而當(dāng)這樣設(shè)計了之后,在訂單上游還需要一層業(yè)務(wù)編排層來對訂單數(shù)據(jù)的流轉(zhuǎn)進(jìn)行處理,以保證對應(yīng)的對象不會錯誤地進(jìn)入到。

按照這樣的設(shè)計思想,如果在在這個基礎(chǔ)上新增一個“分銷訂單”。我們就需要調(diào)整三個地方:新增分銷訂單對象、新增分銷訂單服務(wù)、調(diào)整上游編排層。顯然這不符合開閉原則,同時業(yè)務(wù)開發(fā)的成本也提高。

注:我們可以通過設(shè)計模式優(yōu)化最終實現(xiàn)的邏輯,但是設(shè)計思想是這樣的。

充血模型

貧血模型的問題在于割裂了領(lǐng)域模型的封裝,那么不對模型的封裝進(jìn)行割裂,而是保留領(lǐng)域模型的原貌進(jìn)行程序設(shè)計,就是充血模型??梢悦枋鰹椋?/p>

將領(lǐng)域模型中的方法直接在領(lǐng)域?qū)ο笾袑崿F(xiàn),就是充血模型設(shè)計。

根據(jù)上文中的訂單領(lǐng)域模型,如果我們換成充血模型設(shè)計,就變?yōu)榱耍?/p>

可以看到,如果采用充血模型的設(shè)計,訂單的實體對象中是包含領(lǐng)域模型中的方法的,也就是說下單的實際邏輯由訂單對象自己完成。而對于訂單對象中的子對象,也僅需要繼承訂單對象,然后實現(xiàn)自己的下單方法即可。使用充血模型設(shè)計后我們發(fā)現(xiàn)仍然有訂單對應(yīng)的服務(wù),但是這個服務(wù)僅執(zhí)行一個調(diào)用訂單對象中對應(yīng)邏輯的作用,而這樣的服務(wù)是不關(guān)心具體調(diào)用的是哪一個子類的。

所以,我們使用充血模型設(shè)計,當(dāng)需要新增一個“分銷訂單”時,就只需要創(chuàng)建一個訂單的新的子類,然后在類中實現(xiàn)對應(yīng)的下單邏輯就可以了,而這是符合開閉原則的。

而由于充血模型還原的是領(lǐng)域模型的原貌,所以在依據(jù)領(lǐng)域模型進(jìn)行程序設(shè)計的時候,其映射關(guān)系直觀,所以對應(yīng)的代碼修改就更直接。

貧血模型VS充血模型

通過上文分析,充血模型是全面優(yōu)于貧血模型的。但是在實際的開發(fā)應(yīng)用中并非如此。

貧血模型比充血模型實現(xiàn)更簡單

由于充血模型是還原領(lǐng)域模型的原貌,所以在進(jìn)行程序的操作的時候,需要將模型下的所有組合、聚合對象都進(jìn)行組裝,以訂單為例,訂單需要:訂單、訂單明細(xì)、用戶、用戶地址、商品等5個對象進(jìn)行封裝。而由于封裝的復(fù)雜性,所以還需要設(shè)計訂單倉庫、訂單工廠等組件用于創(chuàng)建訂單的對象。同時因為創(chuàng)建后的對象大小可能會比較大,訂單倉庫中一般還需要進(jìn)行緩存設(shè)計??偟膩碚f:

充血模型要依靠強(qiáng)大的技術(shù)平臺來維護(hù)模型的使用。

而因為貧血模型是通過將模型之間進(jìn)行分割而實現(xiàn)的,所以當(dāng)操作訂單的時候,只需根據(jù)需要操作訂單、訂單明細(xì)就可以。而一般的三層設(shè)計Controller、Service、Dao就可以支撐起來訂單的模型設(shè)計。由于分割的模型數(shù)據(jù)不必組裝成領(lǐng)域模型對象,所以在Dao查詢完畢數(shù)據(jù)后,可以直接返回給Service進(jìn)行使用,反之亦然。系統(tǒng)的復(fù)雜性大大降低。

貧血模型簡單直接,可在經(jīng)典三層中直接實現(xiàn)。

充血模型需要具備更強(qiáng)的設(shè)計能力

由于充血模型是對領(lǐng)域模型的直接表現(xiàn),所以領(lǐng)域模型設(shè)計的優(yōu)劣會直接影響到系統(tǒng)的整體性能與擴(kuò)展性。這就要求開發(fā)人員有更強(qiáng)的對象分析、對象設(shè)計能力。同時由于充血模型中需要對不同領(lǐng)域中的數(shù)據(jù)進(jìn)行聚合,所以可能需要在團(tuán)隊之間提出數(shù)據(jù)查詢需求,也就需要有更強(qiáng)的團(tuán)隊協(xié)作能力。

而相反的,貧血模型所有業(yè)務(wù)處理都在service中進(jìn)行操作,且對模型進(jìn)行了分割,所以對于數(shù)據(jù)的外部依賴就更少,層級也更少。大部分邏輯都是直接Dao查詢數(shù)據(jù)庫后返回,對于開發(fā)人員的能力要求就更小。

貧血模型可面向步驟編程

在面對長串的復(fù)雜業(yè)務(wù)場景時,我們可能更傾向于將業(yè)務(wù)拆解為多個串聯(lián)的步驟然后獨立執(zhí)行。而在使用貧血模型的情況下可以通過編寫多個Service直接進(jìn)行面向步驟編程。每個Service可以處理對象中的部分?jǐn)?shù)據(jù),在通過多個Service處理后得到最終結(jié)果。

盡管充血模型也可以在方法中進(jìn)行拆分,但是并不如貧血模型來的直接。

貧血模型AND充血模型

盡管上文中對充血模型與貧血模型進(jìn)行了直接的區(qū)分,但是這兩種設(shè)計并非二元論的。簡單來說,我們可以根據(jù)充血模型與貧血模型的特點,選取我們需要的部分進(jìn)行使用。例如:

  • 將需要封裝的業(yè)務(wù)邏輯到領(lǐng)域?qū)ο笾校凑粘溲P腿ピO(shè)計
  • 將不需要封裝的業(yè)務(wù)邏輯放到Service中,按照貧血模型去設(shè)計

那么針對上文中的訂單模型來說設(shè)計就變成了:

也就是僅將需要封裝的下單邏輯放到了“入駐商家訂單”、“自營訂單”中,而付款、查詢訂單狀態(tài)邏輯則仍然放到Service進(jìn)行主要處理。

事實上,需要封裝的這個概念也是比較模糊的,但是基本上可以參考:

  • 存在繼承、多態(tài)關(guān)系:例如訂單與自營訂單
  • 需要編碼轉(zhuǎn)換:例如根據(jù)數(shù)值返回對應(yīng)的枚舉對象
  • 需要體現(xiàn)出必要領(lǐng)域關(guān)聯(lián)性:例如訂單與訂單明細(xì)的關(guān)系。

最后

盡管經(jīng)過了合理的分析后,得到的結(jié)論是應(yīng)該根據(jù)特性進(jìn)行貧血和充血模型的混用。但是在實際企業(yè)中,如何評判哪些方法可以放到模型中的這個標(biāo)準(zhǔn)是相對模糊的。也就是說更多的還是需要依靠架構(gòu)設(shè)計、開發(fā)的個人能力、代碼review,而上述三個都對小團(tuán)隊、年輕團(tuán)隊不是很友好。所以我認(rèn)為如果為了提高下限,則使用貧血模型更加穩(wěn)妥。


當(dāng)前標(biāo)題:如何選擇充血模型和貧血模型
文章網(wǎng)址:http://www.5511xx.com/article/copedsc.html