概念
VO(View Object):
视图对象,用于展示层,它的作用是把某个指定页面(或组件)的所有数据封装起来。
DTO(Data Transfer Object):
数据传输对象,泛指用于展示层与服务层之间的数据传输对象。
PO(Persistent Object):
持久化对象,就是和数据库保持一致的对象
VO与DTO的区别
1:针对的点不一样
VO : 针对的是视图层,拿去就是直接展示数据
DTO : 针对的是各种之间的数据传递,拿去显示之前可能还会进行数据加工
所以从广义上来说:
层与层之间的传输都可以叫DTO,都可以叫数据传输对象。控制器给视图传递对象,其实也是数据传输,所以也可以叫dto。
只是由于它们之间传递的对象,是用于显示,所以我们又给他取了另外一个更加针对性名字叫vo
在强行解释一波:
大家可能会有个疑问(在笔者参与的项目中,很多程序员也有相同的疑惑):既然DTO是展示层与服务层之间传递数据的对象,为什么还需要一个VO呢?对!对于绝大部分的应用场景来说,DTO和VO的属性值基本是一致的,因此没必要多此一举,但不要忘记这是实现层面的思维,对于设计层面来说,概念上还是应该存在VO和DTO,因为两者有着本质的区别,DTO代表服务层需要接收的数据和返回的数据,而VO代表展示层需要显示的数据。
用一个例子来说明可能会比较容易理解:例如服务层有一个getUser的方法返回一个系统用户,其中有一个属性是gender(性别),对于服务层来说,它只从语义上定义:1-男性,2-女性,0-未指定,而对于展示层来说,它可能需要用“帅哥”代表男性,用“美女”代表女性,用“秘密”代表未指定。说到这里,可能你还会反驳,在服务层直接就返回“帅哥美女”不就行了吗?对于大部分应用来说,这不是问题,但设想一下,如果需求允许客户可以定制风格,而不同风格对于“性别”的表现方式不一样,又或者这个服务同时供多个客户端使用(不同门户),而不同的客户端对于表现层的要求有所不同,那么,问题就来了。再者,回到设计层面上分析,从职责单一原则来看,服务层只负责业务,与具体的表现形式无关,因此,它返回的DTO,不应该出现与表现形式的耦合。
tip: 如果是单一项目 ,其实可以不用分得那么细,从数据库拿出来就是为了展示了,而不是还要给其他层提供服务
在一个单一的项目中常用的做法
1:省略dto
就是把数据取出来的对象,直接返回给控制器层,然后控制器层进行数据加工变成vo,在交给前台。
优点:通用性好,因为取出来的就是全部的字段,在控制器中进行数据加工,可以取到想要的字段,而传输层逻辑不用修改
例如做基础增删改查代码的生成就很方便
缺点:会查询全表,影响效率。当然也可以使用其他方法解决
无图无真相:
2:省略vo
数据库取出来部分字段,放入dto,然后dto传递到控制器,在传递到view中去,也就是说dto充当了各层直接的数据传输
优点: 可以返回自己想要的数据,不同的业务针对性查询 ,不同业务耦合性更低
缺点: 通用性差一点,不同的业务逻辑各层需要独立的写,果从单一职责来看不应该dto 直接丢视图
如图:
3:dto,vo同时存在
dto传递到控制器,控制器在进行一次数据加工,然后传递到view中去
他们同时存在,然后不同的业务逻辑中可以选择,省略dto或者vo或者两同时使用
当然这只是一种情况,其实还可以把各层的dto分得更细一点!这里就不讨论了
在分布式项目中vo,dto,po的做法
分布式项目中,由于项目是独立的,model都是自己项目中的,所以就不存在省略了
个人见解,轻喷
欢迎加群讨论技术,群:677373950(满了,可以加,但通过不了),2群:656732739