生活随笔
收集整理的這篇文章主要介紹了
VO、DTO、DO、PO
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
淺析VO、DTO、DO、PO
概念
VO(View Object) : 視圖對(duì)象,主要對(duì)應(yīng)界面顯示的數(shù)據(jù)對(duì)象。對(duì)于一個(gè)WEB頁面,或者SWT、SWING的一個(gè)界面,用一個(gè)VO對(duì)象對(duì)應(yīng)整個(gè)界面的值。BO(business object) :業(yè)務(wù)對(duì)象,主要作用是把業(yè)務(wù)邏輯封裝為一個(gè)對(duì)象。這個(gè)對(duì)象可以包括一個(gè)或多個(gè)其它的對(duì)象。比如一個(gè)簡(jiǎn)歷,有教育經(jīng)歷、工作經(jīng)歷、社會(huì)關(guān)系等等。我們可以把教育經(jīng)歷對(duì)應(yīng)一個(gè)PO,工作經(jīng)歷對(duì)應(yīng)一個(gè)PO,社會(huì)關(guān)系對(duì)應(yīng)一個(gè)PO。建立一個(gè)對(duì)應(yīng)簡(jiǎn)歷的BO對(duì)象處理簡(jiǎn)歷,每個(gè)BO包含這些PO。這樣處理業(yè)務(wù)邏輯時(shí),我們就可以針對(duì)BO去處理。DTO(Data Transfer Object) :數(shù)據(jù)傳輸對(duì)象,主要用于遠(yuǎn)程調(diào)用等需要大量傳輸對(duì)象的地方。比如我們一張表有100個(gè)字段,那么對(duì)應(yīng)的PO就有100個(gè)屬性。但是我們界面上只要顯示10個(gè)字段,客戶端用WEB service來獲取數(shù)據(jù),沒有必要把整個(gè)PO對(duì)象傳遞到客戶端,這時(shí)我們就可以用只有這10個(gè)屬性的DTO來傳遞結(jié)果到客戶端,這樣也不會(huì)暴露服務(wù)端表結(jié)構(gòu).到達(dá)客戶端以后,如果用這個(gè)對(duì)象來對(duì)應(yīng)界面顯示,那此時(shí)它的身份就轉(zhuǎn)為VO。在這里,我泛指用于展示層與服務(wù)層之間的數(shù)據(jù)傳輸對(duì)象。POJO(plain ordinary java object) :簡(jiǎn)單java對(duì)象,個(gè)人感覺POJO是最常見最多變的對(duì)象,是一個(gè)中間對(duì)象,也是我們最常打交道的對(duì)象。一個(gè)POJO持久化以后就是PO,直接用它傳遞、傳遞過程中就是DTO,直接用來對(duì)應(yīng)表示層就是VO。(POJO、PO、DTO、VO都是處理流程中的名字,不是PO對(duì)應(yīng)一個(gè)POJO,DTO對(duì)應(yīng)一個(gè)POJO,VO對(duì)應(yīng)一個(gè)POJO在有些情況下PO、DTO、VO是指同一個(gè)POJO)DO(Domain Object) 領(lǐng)域?qū)ο?#xff0c;就是從現(xiàn)實(shí)世界中抽象出來的有形或無形的業(yè)務(wù)實(shí)體。PO(Persistent Object) :持久化對(duì)象,它跟持久層(通常是關(guān)系型數(shù)據(jù)庫(kù))的數(shù)據(jù)結(jié)構(gòu)形成一一對(duì)應(yīng)的映射關(guān)系,如果持久層是關(guān)系型數(shù)據(jù)庫(kù),那么,數(shù)據(jù)表中的每個(gè)字段(或若干個(gè))就對(duì)應(yīng)PO的一個(gè)(或若干個(gè))屬性。最形象的理解就是一個(gè)PO就是數(shù)據(jù)庫(kù)中的一條記錄,好處是可以把一條記錄作為一個(gè)對(duì)象處理,可以方便的轉(zhuǎn)為其它對(duì)象。
具體區(qū)別&應(yīng)用
VO與DTO的區(qū)別
大家可能會(huì)有個(gè)疑問:既然DTO是展示層與服務(wù)層之間傳遞數(shù)據(jù)的對(duì)象,為什么還需要一個(gè)VO呢?對(duì)!對(duì)于絕大部分的應(yīng)用場(chǎng)景來說,DTO和VO的屬性值基本是一致的,而且他們通常都是POJO,因此沒必要多此一舉。但不要忘記這是實(shí)現(xiàn)層面的思維,對(duì)于設(shè)計(jì)層面來說,概念上還是應(yīng)該存在VO和DTO,因?yàn)閮烧哂兄举|(zhì)的區(qū)別,DTO代表服務(wù)層需要接收的數(shù)據(jù)和返回的數(shù)據(jù),而VO代表展示層需要顯示的數(shù)據(jù)。
舉個(gè)例子
:例如服務(wù)層有一個(gè)getUser的方法返回一個(gè)系統(tǒng)用戶,其中有一個(gè)屬性是gender(性別),對(duì)于服務(wù)層來說,它只從語義上定義:1-男性,2-女性,0-未指定,而對(duì)于展示層來說,它可能需要用“帥哥”代表男性,用“美女”代表女性,用“秘密”代表未指定。說到這里,可能你還會(huì)反駁,在服務(wù)層直接就返回“帥哥美女”不就行了嗎?對(duì)于大部分應(yīng)用來說,這不是問題,但設(shè)想一下,如果需求允許客戶可以定制風(fēng)格,而不同風(fēng)格對(duì)于“性別”的表現(xiàn)方式不一樣,又或者這個(gè)服務(wù)同時(shí)供多個(gè)客戶端使用(不同門戶),而不同的客戶端對(duì)于表現(xiàn)層的要求有所不同,那么,問題就來了。再者,回到設(shè)計(jì)層面上分析,從職責(zé)單一原則來看,服務(wù)層只負(fù)責(zé)業(yè)務(wù),與具體的表現(xiàn)形式無關(guān),因此,它返回的DTO,不應(yīng)該出現(xiàn)與表現(xiàn)形式的耦合。
VO與DTO的應(yīng)用
為什么不在服務(wù)層中直接返回DO呢?這樣可以省去DTO的編碼和轉(zhuǎn)換工作,原因如下:
兩者在本質(zhì)上的區(qū)別可能導(dǎo)致彼此并不一一對(duì)應(yīng),一個(gè)DTO可能對(duì)應(yīng)多個(gè)DO,反之亦然,甚至兩者存在多對(duì)多的關(guān)系。 DO具有一些不應(yīng)該讓展示層知道的數(shù)據(jù) DO具有業(yè)務(wù)方法,如果直接把DO傳遞給展示層,展示層的代碼就可以繞過服務(wù)層直接調(diào)用它不應(yīng)該訪問的操作,對(duì)于基于AOP攔截服務(wù)層來進(jìn)行訪問控制的機(jī)制來說,這問題尤為突出,而在展示層調(diào)用DO的業(yè)務(wù)方法也會(huì)因?yàn)槭聞?wù)的問題,讓事務(wù)難以控制。 從設(shè)計(jì)層面來說,展示層依賴于服務(wù)層,服務(wù)層依賴于領(lǐng)域?qū)?#xff0c;如果把DO暴露出去,就會(huì)導(dǎo)致展示層直接依賴于領(lǐng)域?qū)?#xff0c;這雖然依然是單向依賴,但這種跨層依賴會(huì)導(dǎo)致不必要的耦合。
DTO應(yīng)該是一個(gè)“扁平的二維對(duì)象”,舉個(gè)例子來說明:如果User會(huì)關(guān)聯(lián)若干個(gè)其他實(shí)體(例如Address、Account、Region等),那么getUser()返回的UserInfo,是否就需要把其關(guān)聯(lián)的對(duì)象的DTO都一并返回呢?如果這樣的話,必然導(dǎo)致數(shù)據(jù)傳輸量的大增,對(duì)于分布式應(yīng)用來說,由于涉及數(shù)據(jù)在網(wǎng)絡(luò)上的傳輸、序列化和反序列化,這種設(shè)計(jì)更不可接受。如果getUser除了要返回User的基本信息外,還需要返回一個(gè)AccountId、AccountName、RegionId、RegionName,那么,請(qǐng)把這些屬性定義到UserInfo中,把一個(gè)“立體”的對(duì)象樹“壓扁”成一個(gè)“扁平的二維對(duì)象”。
這里說的非常好,DTO和DO交互時(shí),或者DTO直接和PO交互時(shí),DO和PO中非常多的字段,DTO是不使用的,不應(yīng)該全部帶過來,只需要把DO和PO中需要的字段Copy到DTO中,然后再進(jìn)行轉(zhuǎn)換。有的同學(xué)為了圖方便,DTO是直接繼承PO或者DO(我之前就這個(gè)干過),然后DTO又和PO的字段是一致的,導(dǎo)致通過PO吐出的字段超級(jí)多,數(shù)據(jù)傳輸大不說,關(guān)鍵是接口輸出時(shí),一大坨字段,抓不住重點(diǎn)。
DO與PO的區(qū)別
DO和PO在絕大部分情況下是一一對(duì)應(yīng)的,PO是只含有g(shù)et/set方法的POJO,但某些場(chǎng)景還是能反映出兩者在概念上存在本質(zhì)的區(qū)別:
DO在某些場(chǎng)景下不需要進(jìn)行顯式的持久化,例如利用策略模式設(shè)計(jì)的商品折扣策略,會(huì)衍生出折扣策略的接口和不同折扣策略實(shí)現(xiàn)類,這些折扣策略實(shí)現(xiàn)類可以算是DO,但它們只駐留在靜態(tài)內(nèi)存,不需要持久化到持久層,因此,這類DO是不存在對(duì)應(yīng)的PO的。 同樣的道理,某些場(chǎng)景下,PO也沒有對(duì)應(yīng)的DO,例如老師Teacher和學(xué)生Student存在多對(duì)多的關(guān)系,在關(guān)系數(shù)據(jù)庫(kù)中,這種關(guān)系需要表現(xiàn)為一個(gè)中間表,也就對(duì)應(yīng)有一個(gè)TeacherAndStudentPO的PO,但這個(gè)PO在業(yè)務(wù)領(lǐng)域沒有任何現(xiàn)實(shí)的意義,它完全不能與任何DO對(duì)應(yīng)上。 某些情況下,為了某種持久化策略或者性能的考慮,一個(gè)PO可能對(duì)應(yīng)多個(gè)DO,反之亦然。
舉兩個(gè)例子:客戶Customer有其聯(lián)系信息Contacts,這里是兩個(gè)一對(duì)一關(guān)系的DO,但可能出于性能的考慮(極端情況,權(quán)作舉例),為了減少數(shù)據(jù)庫(kù)的連接查詢操作,把Customer和Contacts兩個(gè)DO數(shù)據(jù)合并到一張數(shù)據(jù)表中。反過來,“角色”與“資源”之間存在多對(duì)多關(guān)系,會(huì)存放到多張表中,而這種關(guān)系很明顯會(huì)表現(xiàn)為一個(gè)DO——“權(quán)限”。
PO的某些屬性值對(duì)于DO沒有任何意義,這些屬性值可能是為了解決某些持久化策略而存在的數(shù)據(jù),例如為了實(shí)現(xiàn)“樂觀鎖”,PO存在一個(gè)version的屬性,這個(gè)version對(duì)于DO來說是沒有任何業(yè)務(wù)意義的,它不應(yīng)該在DO中存在。同理,DO中也可能存在不需要持久化的屬性。
總結(jié):DO和PO是兩個(gè)層級(jí)的概念,兩者存在一對(duì)一、一對(duì)多和多對(duì)一的關(guān)系。這兩個(gè)層級(jí)的字段,DO不需要包括全部的PO,比如PO中的創(chuàng)建、刪除標(biāo)記、自動(dòng)生成的ID等,PO可以不用關(guān)注。
總結(jié)
以上是生活随笔 為你收集整理的VO、DTO、DO、PO 的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。