一篇文章讲清楚VO,BO,PO,DO,DTO的区别

本文详细解析了编程中的DTO、VO、PO、BO和DO概念,包括它们在前后端交互、数据处理和业务逻辑中的角色,并提供实际应用建议。

随着编程工业化水平的不断加深,各种编程模型层出不穷(比如MVC,MVP等等),伴随着这些编程模型,又有一大批新的概念蜂拥而至,什么VO,BO,PO,DO,DTO之类的,这些新的概念一直以来都是云里雾里,网上虽然也有不少文章来区分这些概念,但看下来基本都是几篇相同的文章转载来转载去,这些文章本身也说的不明,有些还互相矛盾,再加上有些文章在简化系统里面来使用这些概念,让人越看越迷糊

什么原因造成了这种混乱的状态,就不深究了,感觉也很难究出所以然来
因此让我们立足这些概念本身,达成对概念理解的一致性,就足够了,这也是这边文章的主要目的
鉴于专业术语的解释互联网上太多,一搜一大把,我就不重复一遍术语了,而且说实话,术语太抽象,不利于理解,看完其实没解决啥疑惑,我会尽量用大白话(人话)来做解释,争取让大家都能看明白

废话不多说,先来看张图
看完图估计大部分人就已经有了一个直观的感受了

面对这个图,让我们先从承上启下的DTO开始入手

DTO(Data Transfer Object)数据传输对象

这个传输通常指的前后端之间的传输

DTO是一个比较特殊的对象,他有两种存在形式:

在后端,他的存在形式是java对象,也就是在controller里面定义的那个东东,通常在后端不需要关心怎么从json转成java对象的,这个都是由一些成熟的框架帮你完成啦,比如spring框架

在前端,他的存在形式通常是js里面的对象(也可以简单理解成json),也就是通过ajax请求的那个数据体

这也是为什么把他画成横跨两层的原因

这里可能会遇到个问题,现在微服务盛行,服务和服务之间调用的传输对象能叫DTO吗?
我的理解是看情况
DTO本身的一个隐含的意义是要能够完整的表达一个业务模块的输出
如果服务和服务之间相对独立,那就可以叫DTO
如果服务和服务之间不独立,每个都不是一个完整的业务模块,拆开可能仅仅是因为计算复杂度或者性能的问题,那这就不能够叫做DTO,只能是BO

VO(Value Object)值对象
VO就是展示用的数据,不管展示方式是网页,还是客户端,还是APP,只要是这个东西是让人看到的,这就叫VO
VO主要的存在形式就是js里面的对象(也可以简单理解成json)

VO和DTO的区别
主要有两个区别
一个是字段不一样,VO根据需要会删减一些字段
另一个是值不一样,VO会根据需要对DTO中的值进行展示业务的解释
举个简单的例子
DTO可能是这样的

{
    "gender":"男", 
    "age":35 
} 

对于业务一来说只需要性别,而且因为是一个古风聊天室,也不能直接展示男,因此经过业务解释业务一的VO是

{ 
    "gender":"公子" 
} 

对于业务二来说只需要年龄,而且不需要精确的年龄,因此经过业务解释业务二的VO是

{ 
    "age":"30~39" 
} 

PO(Persistant Object)持久对象
PO比较好理解
简单说PO就是数据库中的记录,一个PO的数据结构对应着库中表的结构,表中的一条记录就是一个PO对象
通常PO里面除了get,set之外没有别的方法
对于PO来说,数量是相对固定的,一定不会超过数据库表的数量
等同于Entity,这俩概念是一致的

BO(Business Object)业务对象
BO就是PO的组合
简单的例子比如说PO是一条交易记录,BO是一个人全部的交易记录集合对象
复杂点儿的例子PO1是交易记录,PO2是登录记录,PO3是商品浏览记录,PO4是添加购物车记录,PO5是搜索记录,BO是个人网站行为对象
BO是一个业务对象,一类业务就会对应一个BO,数量上没有限制,而且BO会有很多业务操作,也就是说除了get,set方法以外,BO会有很多针对自身数据进行计算的方法
为什么BO也画成横跨两层呢?原因是现在很多持久层框架自身就提供了数据组合的功能,因此BO有可能是在业务层由业务来拼装PO而成,也有可能是在数据库访问层由框架直接生成
很多情况下为了追求查询的效率,框架跳过PO直接生成BO的情况非常普遍,PO只是用来增删改使用

BO和DTO的区别
这两个的区别主要是就是字段的删减
BO对内,为了进行业务计算需要辅助数据,或者是一个业务有多个对外的接口,BO可能会含有很多接口对外所不需要的数据,因此DTO需要在BO的基础上,只要自己需要的数据,然后对外提供
在这个关系上,通常不会有数据内容的变化,内容变化要么在BO内部业务计算的时候完成,要么在解释VO的时候完成

OK,到这里这些关系基本就理清楚了

等等,DO是什么
DO呢,标题不是还有个DO么?
上面这些概念基本上已经涵盖了全部的流程,DO只是跟其中一个概念相同
但是跟哪个概念相同呢?
现在主要有两个版本
一个是阿里巴巴的开发手册中的定义
DO( Data Object)这个等同于上面的PO
另一个是在DDD(Domain-Driven Design)领域驱动设计
DO(Domain Object)这个等同于上面的BO

最后,让我们再说说实际应用
这几个概念很完整,我们在用的时候是必须按这个来做吗?
当然不是的,系统和系统的复杂度不同,协作水平不同,完全没有必要教条主义,这些概念全上
上哪些概念,省哪些,我给一些实际建议
1,PO这个没法省,不管叫PO还是Entity,怎么着都得有
2,一些工具类的系统和一些业务不是很复杂的系统DTO是可以和BO合并成一个,当业务扩展的时候注意拆分就行
3,VO是可以第一个优化掉的,展示业务不复杂的可以压根儿不要,直接用DTO
4,这也是最重要的一条,概念是给人用的,多人协作的时候一定要保证大家的概念一致,赶紧把这篇文章转发给跟你协作的人吧

 

<think>我们正在讨论软件开发中的不同对象模型:VO,BO,PO,DO,DTO。根据提供的引用,我们可以总结如下:1.**PO(PersistentObject)**:持久化对象,与数据库表结构一一对应,通过DAO层操作。2.**VO(ViewObject)**:视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。3.**BO(BusinessObject)**:业务对象,由服务层输出的封装业务逻辑的对象。4.**DTO(DataTransferObject)**:数据传输对象,用于跨进程或跨网络传输数据,以减少调用次数。5.**DO(DomainObject)**:领域对象,即业务实体,在领域驱动设计中常用。但注意引用[3]提到,有时DO也被理解为DataObject(数据对象),所以具体含义需看上下文。6.**POJO(PlainOrdinaryJavaObject)**:简单的Java对象,没有继承特定类或实现特定接口,可以作为POVODTO等使用,是一种设计理念。引用[1]提到,在需要组装多个DTO来构建一个大视图时,可以考虑使用VO。同时,在服务层设计时,需要权衡是否提供一个返回大视图的DTO。引用[2]和[3]都强调了DAO的作用:将POJO持久化为PO,并用PO组装成VODTO等。它们之间的区别和联系:-**PO**与数据库表对应,由DAO操作。-**VO**用于展示层,通常由PODTO转换而来。-**BO**包含业务逻辑,可能由多个PO组合而成。-**DTO**用于传输数据,通常用于服务层与展示层之间或不同服务之间。-**DO**在领域驱动设计中,代表领域对象,与业务相关。-**POJO**是一个普通Java对象,是上述对象的基础。注意:在实际项目中,这些对象并非必须全部使用,可以根据项目规模和复杂度进行取舍。例如,小型项目可能只用POJO和DTO,而大型项目可能会严格区分。相关问题:1.在微服务架构中,DTOVO的使用有什么特殊考虑?2.如何设计一个对象转换器来高效地转换PODTOVO等?3.领域驱动设计(DDD)中的DO与传统的POJO有什么区别?</think>### VOBOPODODTO 在软件开发中的区别 在软件开发中,这些对象模型用于不同层次的数据封装,核心区别在于**职责边界**和**使用场景**。以下是详细解析(引用自提供的资料): #### 1. **PO (Persistent Object) 持久化对象** - **职责**:与数据库表结构严格对应,代表数据库中的一条记录。 - **特征**: - 通常包含数据库字段的属性和 getter/setter 方法 - 通过 DAO (Data Access Object) 操作数据库[^2][^3] - **示例**: ```java // 用户表对应的PO class UserPO { private Long id; // 对应数据库id字段 private String name; // 对应数据库name字段 // getter/setter } ``` #### 2. **DTO (Data Transfer Object) 数据传输对象** - **职责**:跨进程或跨网络传输数据,**减少调用次数**(如微服务间通信)[^1][^3]。 - **特征**: - 聚合多个 PO 的数据,避免多次远程调用 - 不包含业务逻辑,仅承载数据 - **示例**: ```java // 用户信息+订单信息的聚合DTO class UserOrderDTO { private String userName; // 来自UserPO private List<Order> orders; // 来自OrderPO } ``` #### 3. **VO (View Object) 视图对象** - **职责**:封装前端页面所需数据,**适配展示逻辑**[^1][^3]。 - **特征**: - 根据前端需求组合/转换数据(如日期格式化、状态码转文字) - 常用于 MVC 模型的 Controller → View 层 - **示例**: ```java // 前端需要的用户详情VO class UserDetailVO { private String name; private String statusDesc; // 将状态码0/1转为"正常"/"冻结" } ``` #### 4. **BO (Business Object) 业务对象** - **职责**:封装**业务逻辑**和**领域模型**[^1][^3]。 - **特征**: - 包含业务方法(如订单状态校验、库存计算) - 可能由多个 PO 组合而成 - **示例**: ```java class OrderBO { private OrderPO orderPO; private UserPO userPO; // 业务方法:检查订单是否可取消 public boolean isCancelable() { return orderPO.getStatus() == Status.NEW; } } ``` #### 5. **DO (Domain Object) 领域对象** - **定位**:与 BO 类似,但更强调**领域驱动设计(DDD)** 中的核心模型[^3]。 - **注意**:部分文献中 DOPO 混用(如"Data Object"),需根据项目规范区分[^3]。 #### 6. **POJO (Plain Ordinary Java Object)** - **本质**:简单 Java 对象(无继承特定类/接口),可作为上述对象的基础[^2][^3]。 --- ### 关键区别总结 | 对象 | 核心目的 | 典型应用场景 | 是否含业务逻辑 | |------|--------------------------|----------------------------|--------------| | PO | 映射数据库 | DAO 层操作数据库 | ❌ | | DTO | 跨层/跨服务数据传输 | 微服务接口参数/返回值 | ❌ | | VO | 适配前端展示 | Controller 返回给前端的数据 | ❌ | | BO | 封装业务规则 | Service 层业务处理 | ✔️ | | DO | 领域模型(DDD) | 领域层核心逻辑 | ✔️ | > 引用说明: > [^1]: 在需要组装多个DTO构建大视图时优先使用VO,服务层设计需权衡是否提供聚合DTO。 > [^2]: DAO 负责将 POJO 持久化为 PO,再用 PO 组装 VO/DTO。 > [^3]: 对象转换需根据项目实际调整,避免过度设计。 --- ### 相关问题 1. **在微服务架构中,DTOVO 是否必须同时存在?如何权衡?** (参考引用[1]中服务层提供聚合DTO的权衡点) 2. **领域驱动设计(DDD)中,DOBO 的关系是什么?** (结合引用[3]中 DO 的领域模型特性) 3. **如何设计高效的 PODTO/VO 转换机制?** (可讨论工具类 vs 框架转换的性能取舍) 4. **什么场景下 PO 可以直接作为 VO 使用?是否存在风险?** (分析数据库字段与前端需求的耦合问题)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值