概述
在这篇教程中,我们将学习什么是数据传输对象(DTO)、值对象(VO)、简单的Java对象(POJO)以及JavaBeans。我们将探讨它们之间的区别,并了解在何时使用哪种类型。
2. 简单的Java对象(POJO)
POJO,即普通的Java对象,不依赖于任何特定框架。 这个术语用于指代一个简单、轻量级的Java对象。
POJO的属性和方法没有特定的命名约定。
让我们定义一个基础的EmployeePOJO
对象,它有三个属性:
public class EmployeePOJO {
private String firstName;
private String lastName;
private LocalDate startDate;
public EmployeePOJO(String firstName, String lastName, LocalDate startDate) {
this.firstName = firstName;
this.lastName = lastName;
this.startDate = startDate;
}
public String name() {
return this.firstName + " " + this.lastName;
}
public LocalDate getStart() {
return this.startDate;
}
}
如我们所见,这个Java对象定义了一个表示员工的结构,不依赖于任何框架。
3. JavaBeans
3.1. JavaBeans是什么?
JavaBeans是一种特殊的POJO,它有一些关于如何实现的严格规则。 规则规定它应该是可序列化的,有空构造函数,并且允许通过遵循getX()
和setX()
惯例的方法访问变量。
3.2. POJO作为JavaBeans
由于JavaBean本质上是POJO,让我们通过实现必要的bean规则将EmployeePOJO
转换为JavaBean:
public class EmployeeBean implements Serializable {
private static final long serialVersionUID = -3760445487636086034L;
private String firstName;
private String lastName;
private LocalDate startDate;
public EmployeeBean() {
}
public EmployeeBean(String firstName, String lastName, LocalDate startDate) {
this.firstName = firstName;
this.lastName = lastName;
this.startDate = startDate;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
// additional getters and setters
}
为了将POJO转换为JavaBean,我们实现了Serializable
接口,将属性标记为私有,并使用getter/setter方法来访问属性。
4. DTO
4.1. DTO模式
DTO,也称为数据传输对象,封装值以在进程或网络之间传递数据。
这有助于减少调用的方法数量。通过在一个调用中包含多个参数或值,我们减少了远程操作中的网络开销。
这个模式的一个优势是封装了序列化逻辑。它使程序能够以特定格式存储和传输数据。
DTO没有明确的行为。它主要通过将领域模型与表现层解耦,帮助使代码松散耦合。
4.2. 如何使用DTO?
DTO具有扁平结构,没有业务逻辑。它们使用与POJO相同的格式。DTO只包含存储、访问器和与序列化或解析相关的方法。
DTO基本上映射到域模型,并将数据发送到方法或服务器。
让我们创建一个名为EmployeeDTO
的DTO,它包含了创建员工所需的所有必要详细信息。我们将一次性将这些数据发送到服务器,以优化API交互:
public class EmployeeDTO {
private String firstName;
private String lastName;
private LocalDate startDate;
// standard getters and setters
}
上述DTO与不同的服务交互并处理数据流。这种DTO模式可以在任何服务中使用,不受框架限制。
5. 值对象(VO)
VO,也称为值对象,是一种特殊类型的对象,可以持有值,如java.lang.Integer
和java.lang.Long
。
值对象始终应重写equals()
和hashCode()
方法。VO通常封装小的对象,如数字、日期、字符串等。它们遵循值语义,即直接改变对象的值,而不是传递引用。
让值对象不可变是一个好实践。只有通过创建新对象来更改值,而不是直接更新旧对象本身的值。这有助于理解两个创建相等的值对象应该始终保持相等的隐含合同。
让我们定义EmployeeVO
并重写equals()
和hashCode()
方法:
public final class EmployeeVO {
private final String firstName;
private final String lastName;
private final LocalDate startDate;
public EmployeeVO(String firstName, String lastName, LocalDate startDate) {
this.firstName = firstName;
this.lastName = lastName;
this.startDate = startDate;
}
// Getters
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
EmployeeVO emp = (EmployeeVO) obj;
return Objects.equals(firstName, emp.firstName)
&& Objects.equals(lastName, emp.lastName)
&& Objects.equals(startDate, emp.startDate);
}
@Override
public int hashCode() {
return Objects.hash(firstName, lastName, startDate);
}
}
6. 总结
在这篇文章中,我们了解了POJO、JavaBeans、DTO和Value Objects的定义。我们还看到了一些框架和库如何利用JavaBean的命名约定,以及如何将POJO转换为JavaBean。我们还探讨了DTO模式和Value Objects,以及它们在不同场景下的使用。
接下来,Java 14的记录增强了可读性,通过抽象getter、setter、equals和hashCode,并提供了一键式不可变性。更多关于此的信息,请参阅我们的文章:这里。
一如既往,这些示例的代码可以在GitHub上找到:此处。