对象思想

对象思想

一、PO : persistent object 持久对象

1、有时候也被为 Data 对象,对应数据库中的 entity,可以简单认为一个 PO 对应数据库中的一条记录。
2、在 hibernate 持久化框架中与 insert/delet 操作密切相关。
3、PO 中不应该包含任何对数据库的操作。
持久化对象,它跟持久层(通常是关系型数据库)的数据结构形成一一对应的映射关系,如果持久层是关系型数据库,那么,数据表中的每个字段(或若干个)就对应 PO 的一个(或若干个)属性。

二、POJO : plain ordinary java object 无规则简单 java 对象

使用 POJO 名称是为了避免和 EJB 混淆起来, 而且简称比较直接。其中有一些属性及其 getter setter 方法的类,没有业务逻辑,有时可以作为 VO(value-object) 或 DTO(Data Transform Object) 来使用.当然,如果你有一个简单的运算属性也是可以的,但不允许有业务方法,也不能携带有 connection 之类的方法。
POJO 是 Plain Old Java Objects 的缩写不错,但是它通指没有使用 Entity Beans 的普通 java 对象,可以把 POJO 作为支持业务逻辑的协助类。
POJO 有一些 private 的参数作为对象的属性。然后针对每个参数定义了 get 和 set 方法作为访问的接口。
POJO 是 MartinFowler 等发明的一个术语,用来表示普通的 Java 对象,不是 JavaBean, EntityBean 或者 SessionBean。 POJO 不担当任何特殊的角色,也不实现任何特殊的 Java 框架的接口如,EJB, JDBC 等等。
即 POJO 是一个简单的普通的 Java 对象,它不包含业务逻辑或持久逻辑等,但不是 JavaBean、EntityBean 等,不具有任何特殊角色和不继承或不实现任何其它 Java 框架的类或接口。

一个中间对象,可以转化为 PO、DTO、VO。

  • 1、POJO 持久化之后 ==〉PO
    在运行期,由 Hibernate 中的 cglib 动态把 POJO 转换为 PO,PO 相对于 POJO 会增加一些用来管理数据库 entity 状态的属性和方法。PO 对于 programmer 来说完全透明,由于是运行期生成 PO,所以可以支持增量编译,增量调试。
  • 2、POJO 传输过程中 ==〉DTO
  • 3、POJO 用作表示层 ==〉VO

三、BO : business object 业务对象

封装业务逻辑为一个对象(可以包括多个 PO,通常需要将 BO 转化成 PO,才能进行数据的持久化,反之,从 DB 中得到的 PO,需要转化成 BO 才能在业务层使用)。
关于 BO 主要有三种概念
1、只包含业务对象的属性;
2、只包含业务方法;
3、两者都包含。
在实际使用中,认为哪一种概念正确并不重要,关键是实际应用中适合自己项目的需要。

四、VO : value object 值对象 / view object表现层对象

1、主要对应页面显示(web 页面 / swt、swing 界面)的数据对象。
2、可以和表对应,也可以不,这根据业务的需要。
注 :在 struts 中,用 ActionForm 做 VO,需要做一个转换,因为PO是面向对象的,而 ActionForm 是和 view 对应的,要将几个 PO 要显示的属性合成一个 ActionForm,可以使用 BeanUtils 的 copy 方法。

五、DTO(TO) : Data Transfer Object 数据传输对象

1、用在需要跨进程或远程传输时,它不应该包含业务逻辑。
2、比如一张表有100个字段,那么对应的PO就有100个属性(大多数情况下,DTO 内的数据来自多个表)。但 view 层只需显示10个字段,没有必要把整个 PO 对象传递到 client,这时我们就可以用只有这10个属性的 DTO 来传输数据到 client,这样也不会暴露 server 端表结构。到达客户端以后,如果用这个对象来对应界面显示,那此时它的身份就转为 VO。

六、DAO : data access object 数据访问对象

1、主要用来封装对 DB 的访问(CRUD 操作)。
2、通过接收 Business 层的数据,把 POJO 持久化为 PO。

七、DO(Domain Object) : 领域对象,就是从现实世界中抽象出来的有形或无形的业务实体。

八、区别

8.1、POJO 和 JaveBean 的区别

POJO 的内在含义是指那些没有从任何类继承、也没有实现任何接口,更没有被其它框架侵入的 java 对象。
JavaBean 则比 POJO 复杂很多,Java Bean 是可复用的组件,对 Java Bean 并没有严格的规范,理论上讲,任何一个 Java 类都可以是一个 Bean 。但通常情况下,由于 Java Bean 是被容器所创建(如 Tomcat) 的,所以 Java Bean 应具有一个无参的构造器,另外,通常 Java Bean 还要实现 Serializable 接口用于实现 Bean 的持久性。 Java Bean 是不能被跨进程访问的。JavaBean 是一种组件技术,

8.2、VO 和 DTO 的区别

既然DTO是展示层与服务层之间传递数据的对象,为什么还需要一个 VO 呢?对于绝大部分的应用场景来说,DTO 和 VO 的属性值基本是一致的,而且他们通常都是 POJO,因此没必要多此一举,但不要忘记这是实现层面的思维,对于设计层面来说,概念上还是应该存在 VO 和 DTO,因为两者有着本质的区别,DTO 代表服务层需要接收的数据和返回的数据,而 VO 代表展示层需要显示的数据。

public xxDto getxxList(xxDto dto){}  //服务层  
xxDto-->xxVo  //控制层(展示层)  
或者:public xxVo getxxList(xxDto dto)  //服务层  

dto --> vo 例子:
例如服务层有一个 getUser 的方法返回一个系统用户,其中有一个属性是gender(性别),对于服务层来说,它只从语义上定义:1-男性,2-女性,0-未指定,而对于展示层来说,它可能需要用“帅哥”代表男性,用“美女”代表女性,用“秘密”代表未指定。说到这里,可能你还会反驳,在服务层直接就返回“帅哥美女”不就行了吗?对于大部分应用来说,这不是问题,但设想一下,如果需求允许客户可以定制风格,而不同风格对于“性别”的表现方式不一样,又或者这个服务同时供多个客户端使用(不同门户),而不同的客户端对于表现层的要求有所不同,那么,问题就来了。再者,回到设计层面上分析,从职责单一原则来看,服务层只负责业务,与具体的表现形式无关,因此,它返回的 DTO,不应该出现与表现形式的耦合。

8.3、DTO 与 DO 的区别

概念上,DTO 是展示层和服务层之间的数据传输对象(可以认为是两者之间的协议),而 DO 是对现实世界各种业务角色的抽象,这就引出了两者在数据上的区别,例如 UserInfo 和 User(对于 DTO 和 DO 的命名规则),对于一个 getUser 方法来说,本质上它永远不应该返回用户的密码,因此 UserInfo 至少比 User 少一个 password 的数据。而在领域驱动设计中,正如第一篇系列文章所说,DO 不是简单的 POJO,它具有领域业务逻辑。

8.4、DO 和 PO 的区别

DO 和 PO 在绝大部分情况下是一一对应的,PO 是只含有 get/set 方法的 POJO,但某些场景还是能反映出两者在概念上存在本质的区别:

DO 在某些场景下不需要进行显式的持久化,例如利用策略模式设计的商品折扣策略,会衍生出折扣策略的接口和不同折扣策略实现类,这些折扣策略实现类可以算是 DO,但它们只驻留在静态内存,不需要持久化到持久层,因此,这类 DO 是不存在对应的 PO 的。

同样的道理,某些场景下,PO 也没有对应的 DO,例如老师 Teacher 和学生 Student 存在多对多的关系,在关系数据库中,这种关系需要表现为一个中间表,也就对应有一个 TeacherAndStudentPO 的 PO,但这个 PO 在业务领域没有任何现实的意义,它完全不能与任何 DO 对应上。这里要特别声明,并不是所有多对多关系都没有业务含义,这跟具体业务场景有关,例如:两个PO之间的关系会影响具体业务,并且这种关系存在多种类型,那么这种多对多关系也应该表现为一个 DO,又如:“角色”与“资源”之间存在多对多关系,而这种关系很明显会表现为一个 DO——“权限”。

某些情况下,为了某种持久化策略或者性能的考虑,一个 PO 可能对应多个 DO,反之亦然。例如客户Customer有其联系信息 Contacts,这里是两个一对一关系的 DO,但可能出于性能的考虑(极端情况,权作举例),为了减少数据库的连接查询操作,把 Customer 和 Contacts 两个 DO 数据合并到一张数据表中。反过来,如果一本图书 Book,有一个属性是封面 cover,但该属性是一副图片的二进制数据,而某些查询操作不希望把 cover 一并加载,从而减轻磁盘 IO 开销,同时假设 ORM 框架不支持属性级别的延迟加载,那么就需要考虑把 cover 独立到一张数据表中去,这样就形成一个 DO 对应对个 PO 的情况。

PO 的某些属性值对于 DO 没有任何意义,这些属性值可能是为了解决某些持久化策略而存在的数据,例如为了实现“乐观锁”, PO 存在一个 version 的属性,这个 version 对于 DO 来说是没有任何业务意义的,它不应该在 DO 中存在。同理,DO 中也可能存在不需要持久化的属性。

总体上来说都是概念基本一致,视角略有不同而已。

评论

暂无

添加新评论