PO (Persistent Object)
- 全称:Persistent Object(持久化对象)。
- 用途:用于与数据库表直接映射的对象。
- 特点:
- 通常与数据库表一一对应。
- 包含与数据库字段对应的属性和方法。
- 用于 ORM(对象关系映射)框架(如 MyBatis、Hibernate)操作数据库。
public class UserPO {
private Long id;
private String username;
private String password;
private Date createTime;
// Getter 和 Setter 方法
}
DTO (Data Transfer Object)
- 全称:Data Transfer Object(数据传输对象)。
- 用途:用于在不同层(如 Controller 层和 Service 层)之间传输数据。
- 特点:
- 通常不包含业务逻辑。
- 用于封装多个字段,减少网络传输次数。
- 可以根据需要组合或拆分数据
public class UserDTO {
private Long id;
private String username;
private String email;
// Getter 和 Setter 方法
}
1. VO 的定义
- 全称:Value Object(值对象)。
- 用途:用于封装一组相关的数据,通常表示某个特定的值或概念。
- 特点:
- 不可变性:VO 对象一旦创建,其属性值不可更改。
- 值相等性:两个 VO 对象如果属性值相同,则认为它们是相等的。
- 无行为:VO 通常不包含业务逻辑,仅用于存储数据。
2. VO 的使用场景
- 表示某个具体的值:例如,货币金额、日期范围、坐标点等。
- 封装复杂的数据结构:例如,地址信息、颜色值等。
- 用于领域驱动设计(DDD):在 DDD 中,VO 用于表示领域模型中的值对象。
3. VO 的示例
(1)简单的 VO
java
复制
public class Money {
private final BigDecimal amount;
private final String currency;
public Money(BigDecimal amount, String currency) {
this.amount = amount;
this.currency = currency;
}
public BigDecimal getAmount() {
return amount;
}
public String getCurrency() {
return currency;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Money money = (Money) o;
return Objects.equals(amount, money.amount) && Objects.equals(currency, money.currency);
}
@Override
public int hashCode() {
return Objects.hash(amount, currency);
}
}
(2)复杂的 VO
java
复制
public class Address {
private final String street;
private final String city;
private final String postalCode;
private final String country;
public Address(String street, String city, String postalCode, String country) {
this.street = street;
this.city = city;
this.postalCode = postalCode;
this.country = country;
}
// Getter 方法
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Address address = (Address) o;
return Objects.equals(street, address.street) &&
Objects.equals(city, address.city) &&
Objects.equals(postalCode, address.postalCode) &&
Objects.equals(country, address.country);
}
@Override
public int hashCode() {
return Objects.hash(street, city, postalCode, country);
}
}
4. VO 与其他对象类型的区别
| 类型 | 全称 | 用途 | 特点 | 示例场景 |
|---|---|---|---|---|
| PO | Persistent Object | 与数据库表直接映射的对象 | 与数据库字段一一对应,用于 ORM 操作 | MyBatis、Hibernate 中的实体类 |
| DTO | Data Transfer Object | 在不同层之间传输数据 | 不包含业务逻辑,用于封装数据 | Controller 层与 Service 层之间的数据传输 |
| VO | Value Object | 封装一组相关的数据,表示某个值 | 不可变,值相等性,无行为 | 货币金额、地址信息、坐标点等 |
5. VO 的优点
- 不可变性:确保数据的安全性,避免被意外修改。
- 值相等性:简化对象的比较逻辑。
- 语义清晰:通过 VO 可以更清晰地表达业务概念。
6. 实际应用示例
(1)表示货币金额
java
复制
public class Money {
private final BigDecimal amount;
private final String currency;
public Money(BigDecimal amount, String currency) {
this.amount = amount;
this.currency = currency;
}
public BigDecimal getAmount() {
return amount;
}
public String getCurrency() {
return currency;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Money money = (Money) o;
return Objects.equals(amount, money.amount) && Objects.equals(currency, money.currency);
}
@Override
public int hashCode() {
return Objects.hash(amount, currency);
}
}
(2)表示日期范围
java
复制
public class DateRange {
private final LocalDate startDate;
private final LocalDate endDate;
public DateRange(LocalDate startDate, LocalDate endDate) {
this.startDate = startDate;
this.endDate = endDate;
}
public LocalDate getStartDate() {
return startDate;
}
public LocalDate getEndDate() {
return endDate;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DateRange dateRange = (DateRange) o;
return Objects.equals(startDate, dateRange.startDate) && Objects.equals(endDate, dateRange.endDate);
}
@Override
public int hashCode() {
return Objects.hash(startDate, endDate);
}
}
- VO 是一种用于封装数据的对象类型,具有不可变性和值相等性。
- 它通常用于表示某个具体的值或概念(如货币金额、地址信息等)。
- 与
PO和DTO不同,VO更注重数据的封装和语义表达。
在实际开发中,合理使用 VO 可以提高代码的可读性和可维护性,特别是在领域驱动设计(DDD)中,VO 是表示领域模型的重要组成部分。
2. VO 的使用场景
- 表示某个具体的值:例如,货币金额、日期范围、坐标点等。
- 封装复杂的数据结构:例如,地址信息、颜色值等。
- 用于领域驱动设计(DDD):在 DDD 中,VO 用于表示领域模型中的值对象。
4. VO 与其他对象类型的区别
| 类型 | 全称 | 用途 | 特点 | 示例场景 |
|---|---|---|---|---|
| PO | Persistent Object | 与数据库表直接映射的对象 | 与数据库字段一一对应,用于 ORM 操作 | MyBatis、Hibernate 中的实体类 |
| DTO | Data Transfer Object | 在不同层之间传输数据 | 不包含业务逻辑,用于封装数据 | Controller 层与 Service 层之间的数据传输 |
| VO | Value Object | 封装一组相关的数据,表示某个值 | 不可变,值相等性,无行为 | 货币金额、地址信息、坐标点等 |
5. VO 的优点
- 不可变性:确保数据的安全性,避免被意外修改。
- 值相等性:简化对象的比较逻辑。
- 语义清晰:通过 VO 可以更清晰地表达业务概念。
6. 实际应用示例
(1)表示货币金额
java
复制
public class Money {
private final BigDecimal amount;
private final String currency;
public Money(BigDecimal amount, String currency) {
this.amount = amount;
this.currency = currency;
}
public BigDecimal getAmount() {
return amount;
}
public String getCurrency() {
return currency;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Money money = (Money) o;
return Objects.equals(amount, money.amount) && Objects.equals(currency, money.currency);
}
@Override
public int hashCode() {
return Objects.hash(amount, currency);
}
}
(2)表示日期范围
java
复制
public class DateRange {
private final LocalDate startDate;
private final LocalDate endDate;
public DateRange(LocalDate startDate, LocalDate endDate) {
this.startDate = startDate;
this.endDate = endDate;
}
public LocalDate getStartDate() {
return startDate;
}
public LocalDate getEndDate() {
return endDate;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DateRange dateRange = (DateRange) o;
return Objects.equals(startDate, dateRange.startDate) && Objects.equals(endDate, dateRange.endDate);
}
@Override
public int hashCode() {
return Objects.hash(startDate, endDate);
}
}
7. 总结
- VO 是一种用于封装数据的对象类型,具有不可变性和值相等性。
- 它通常用于表示某个具体的值或概念(如货币金额、地址信息等)。
- 与
PO和DTO不同,VO更注重数据的封装和语义表达。
在实际开发中,合理使用 VO 可以提高代码的可读性和可维护性,特别是在领域驱动设计(DDD)中,VO 是表示领域模型的重要组成部分。
4. VO 与其他对象类型的区别
| 类型 | 全称 | 用途 | 特点 | 示例场景 |
|---|---|---|---|---|
| PO | Persistent Object | 与数据库表直接映射的对象 | 与数据库字段一一对应,用于 ORM 操作 | MyBatis、Hibernate 中的实体类 |
| DTO | Data Transfer Object | 在不同层之间传输数据 | 不包含业务逻辑,用于封装数据 | Controller 层与 Service 层之间的数据传输 |
| VO | Value Object | 封装一组相关的数据,表示某个值 | 不可变,值相等性,无行为 | 货币金额、地址信息、坐标点等 |