DO、DTO、BO、VO、POJO區(qū)別
作者丨安琪拉的博客
來源丨安琪拉的博客
不知道大家在自己的系統(tǒng)中發(fā)現(xiàn)很多類都是以BO、VO、DTO、DO結(jié)尾的類,這些存儲(chǔ)數(shù)據(jù)的簡單類,有什么作用呢?
我理解有二個(gè)作用:
一般稍大的系統(tǒng)都是分層設(shè)計(jì)的,最底層是數(shù)據(jù)存儲(chǔ)層,數(shù)據(jù)庫,最上層是對外提供接口調(diào)用的應(yīng)用/視圖層,那每一層都有關(guān)聯(lián)的數(shù)據(jù)對象,所以需要做相應(yīng)的區(qū)分。
讓類語義更明確,很容易知道類的含義。
定義
先來看看阿里巴巴開發(fā)規(guī)約的定義:
POJO(Plain Ordinary Java Object):在本規(guī)約中,POJO專指只有setter/getter/toString的簡單類,包括DO/DTO/BO/VO等。
【參考】分層領(lǐng)域模型規(guī)約:
DO(Data Object):與數(shù)據(jù)庫表結(jié)構(gòu)一一對應(yīng),通過DAO層向上傳輸數(shù)據(jù)源對象。
DTO(Data Transfer Object):數(shù)據(jù)傳輸對象,Service或Manager向外傳輸?shù)膶ο蟆?/p>
BO(Business Object):業(yè)務(wù)對象??梢杂蒘ervice層輸出的封裝業(yè)務(wù)邏輯的對象。
Query:數(shù)據(jù)查詢對象,各層接收上層的查詢請求。額外規(guī)定:【強(qiáng)制】超過2個(gè)參數(shù)的查詢封裝,禁止使用Map類來傳輸。
VO(View Object):顯示層對象,通常是Web向模板渲染引擎層傳輸?shù)膶ο蟆?/p>
—《阿里巴巴Java開發(fā)規(guī)約》
詳細(xì)各個(gè)詞的定義:
DAO:Data Acess Object,數(shù)據(jù)訪問對象,這個(gè)我們不陌生,跟數(shù)據(jù)庫打交道的系統(tǒng)都會(huì)有這樣的DAO類,主要的作用:
封裝對數(shù)據(jù)庫的訪問,常規(guī)的增刪改查(CRUD操作)都通過DAO來實(shí)現(xiàn)。
PO/DO: Persistent Object / Data Object,持久對象 / 數(shù)據(jù)對象。
跟數(shù)據(jù)庫表是一一對應(yīng)的,一個(gè)PO/DO 數(shù)據(jù)是表的一條記錄。
以前用Hibernate 的時(shí)候PO用的很多,現(xiàn)在普遍喜歡用 DO,這個(gè)看各個(gè)公司自己的規(guī)范。
PO / DO 只是數(shù)據(jù)的對象,不包含任何的操作。舉個(gè)例子,學(xué)生表是StudentDO,對學(xué)生表的增刪改查等操作就是StudentDAO。
DTO:Data Transfer Object,數(shù)據(jù)傳輸對象
在分布式系統(tǒng)中,系統(tǒng)之間可以通過DTO進(jìn)行數(shù)據(jù)傳輸;
DTO也可以在應(yīng)用內(nèi)部,核心層和應(yīng)用層之間傳遞數(shù)據(jù),DTO只是簡單的數(shù)據(jù)傳輸,沒有業(yè)務(wù)邏輯的處理;
有的場景,比如數(shù)據(jù)庫表有10個(gè)字段,id(唯一id)、version(版本號),gmt_create(記錄創(chuàng)建時(shí)間) 這些字段不需要對外提供,所以DTO 可以只取有含義的業(yè)務(wù)字段,DO是和數(shù)據(jù)庫記錄的一一映射,但是DTO只需要按照業(yè)務(wù)需要定義需要的字段。
BO : Business Object, 業(yè)務(wù)對象
BO主要作用是把業(yè)務(wù)邏輯封裝為一個(gè)對象。這個(gè)對象可以包括一個(gè)或多個(gè)其它的對象。
在領(lǐng)域模型中,BO是個(gè)非常重要的概念, BO是最小的業(yè)務(wù)單元。
BO 包含數(shù)據(jù)對象(PO/DO)以及對數(shù)據(jù)的操作。
VO: View Object,視圖模型,展示層對象
對應(yīng)頁面顯示(web頁面/移動(dòng)端H5/Native視圖)的數(shù)據(jù)對象。
舉個(gè)例子,DTO 中時(shí)間Date格式,或者是 yyyyMMddHHmmss的字符串,但是VO需要的是前端展示的格式,需要轉(zhuǎn)成”yyyy年MM月dd月";
實(shí)踐
講了這么多概念,我們再看下實(shí)操,先說命名:
領(lǐng)域模型命名規(guī)約
1) 數(shù)據(jù)對象:xxxDO,xxx即為數(shù)據(jù)表名。
2) 數(shù)據(jù)傳輸對象:xxxDTO,xxx為業(yè)務(wù)領(lǐng)域相關(guān)的名稱。
3) 展示對象:xxxVO,xxx一般為網(wǎng)頁名稱。
4) POJO是DO/DTO/BO/VO的統(tǒng)稱,禁止命名成xxxPOJO
再以學(xué)生檔案管理系統(tǒng)為例,我們現(xiàn)在需要做個(gè)學(xué)生檔案管理的后臺系統(tǒng),按照上面的定義,我們能定義出以下一些對象:
如下圖所示:

DB層這里應(yīng)該叫存儲(chǔ)層,這里只列了DB,還有類似HBase、Redis,泛指儲(chǔ)存數(shù)據(jù)。
以Student表為例,DB層負(fù)責(zé)存儲(chǔ)。
DAO層提供了查詢、刪除、寫入的接口;
DO 就是DAO操作的對象,這里是StudentDO,有時(shí)候也會(huì)省略DO,直接寫Student;
service層或core層是做業(yè)務(wù)邏輯處理的,比如查詢接口,根據(jù)學(xué)生學(xué)號調(diào)用DAO層獲取Student信息,之后做一次數(shù)據(jù)裁剪,只取業(yè)務(wù)字段,例如版本號、自增id、數(shù)據(jù)庫記錄創(chuàng)建時(shí)間等非業(yè)務(wù)字段不取,獲取一個(gè)StudentDTO,然后查詢學(xué)生檔案相關(guān)的ProfileDTO,組裝成ProfileBO,作為檔案領(lǐng)域模型;
業(yè)務(wù)層從service 層拿到這個(gè)BO,對BO做一個(gè)視圖轉(zhuǎn)化,轉(zhuǎn)成VO視圖對象,提供給前端負(fù)責(zé)展示。
大學(xué)剛畢業(yè)實(shí)習(xí)那會(huì)寫了一個(gè)業(yè)務(wù)層直接調(diào)用DAO層的代碼,覺得中間要經(jīng)過服務(wù)層、核心層過于繁瑣,字段都差不多,后面被Team Leader 教學(xué)了。
VO(視圖) 和 DO(數(shù)據(jù)模型)都可能會(huì)隨著需求變化,軟件設(shè)計(jì)的原則是降低耦合,一桿到底這種設(shè)計(jì)就是強(qiáng)耦合(把視圖和數(shù)據(jù)直接綁定),DO變化的時(shí)候因?yàn)镈TO(數(shù)據(jù)傳輸對象)、BO(領(lǐng)域模型)的存在,不需要修改VO,VO修改也同樣不需要修改DO數(shù)據(jù)模型。
發(fā)這個(gè)文章的時(shí)候,發(fā)現(xiàn)一件事,費(fèi)勁巴拉搞的封面只有星標(biāo)和長讀用戶才能看得到,截圖如下:

-End-
最近有一些小伙伴,讓我?guī)兔φ乙恍?nbsp;面試題 資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來,可以說是程序員面試必備!所有資料都整理到網(wǎng)盤了,歡迎下載!

面試題】即可獲取