揭秘Java领域驱动设计:VO、DO、DTO:这些缩写你都懂了吗?
在领域驱动设计(DDD)中,常用的缩写和概念包括以下几种:DO(Domain Object)、DTO(Data Transfer Object)、VO(Value Object)、Entity、Repository、Service、Factory、和Aggregate。我们这里简单总结一下这些概念的使用场景、特点、文件命名规范
VO(Value Object):值对象
命名惯例: 通常使用属性名作为文件名,例如:Address.java
。
VO是不可变的对象,通常用于封装数据,像颜色、坐标或日期这样的简单对象。
使用场景:
- 表示不可变的对象,通常用来描述一些属性的组合,不具有唯一标识符。
- 常用于表示货币、地址等不可变对象。
特点:
- 不可变对象,没有唯一标识符。
- 通常用于表示属性的组合。
代码示例
public class Address {
private final String street;
private final String city;
private final String postalCode;
public Address(String street, String city, String postalCode) {
this.street = street;
this.city = city;
this.postalCode = postalCode;
}
// Getters and no setters to ensure immutability
}
DO(Domain Object):领域对象
命名惯例: 通常使用实体名作为文件名,例如:Order.java
。
DO,表示具有业务含义的实体,例如用户、订单等。这些对象不仅仅包含数据,还可能包含业务逻辑。
使用场景:
- 表示业务领域中的实体,包含业务逻辑和行为。
- 常用于业务逻辑的实现和业务规则的封装。
特点:
- 包含业务逻辑和行为。
- 表示业务领域中的实体或值对象。
代码示例
public class Order {
private String orderId;
private List<OrderItem> items;
private Customer customer;
public Order(String orderId, Customer customer) {
this.orderId = orderId;
this.customer = customer;
this.items = new ArrayList<>();
}
public void addItem(OrderItem item) {
items.add(item);
}
public double calculateTotalPrice() {
return items.stream().mapToDouble(OrderItem::getPrice).sum();
}
// Getters and setters
}
DTO(Data Transfer Object):数据传输对象
命名惯例: 通常在实体名后加上DTO
,例如:OrderDTO.java
。
DTO是为了数据传输而设计的对象,它不包含任何业务逻辑,而仅仅是为了在不同层之间传递数据。例如,一个从数据库层向服务层传递用户信息的UserDTO可能包含用户的姓名、email等。
使用场景:
- 用于在不同层之间传输数据,通常不包含业务逻辑。
- 常用于服务层和数据访问层之间的数据传输。
特点:
- 仅包含数据,不包含业务逻辑。
- 用于数据传输和序列化。
代码示例
public class OrderDTO {
private String orderId;
private List<OrderItemDTO> items;
private String customerId;
// Getters and setters
}
Entity:实体
命名惯例: 通常使用实体名作为文件名,例如:Customer.java
。
使用场景:
- 表示具有唯一标识符的对象,通常是领域对象的一部分。
- 常用于表示数据库中的记录。
特点:
- 具有唯一标识符。
- 通常与数据库表一一对应。
代码示例
public class Customer {
private String customerId;
private String name;
private Address address;
public Customer(String customerId, String name, Address address) {
this.customerId = customerId;
this.name = name;
this.address = address;
}
// Getters and setters
}
Repository:仓库
命名惯例: 通常在实体名后加上Repository
,例如:OrderRepository.java
。
使用场景:
- 提供对聚合的持久化和查询操作,封装数据访问逻辑。
- 常用于数据访问层。
特点:
- 封装数据访问逻辑。
- 提供CRUD操作。
代码示例
public interface OrderRepository {
void save(Order order);
Order findById(String orderId);
List<Order> findAll();
}
Service:服务
命名惯例: 通常在功能名后加上Service
,例如:OrderService.java
。
使用场景:
- 封装业务逻辑的服务,通常分为应用服务和领域服务。
- 常用于处理业务逻辑和协调多个领域对象的操作。
特点:
- 封装业务逻辑。
- 提供业务操作的方法。
代码示例
public class OrderService {
private final OrderRepository orderRepository;
public OrderService(OrderRepository orderRepository) {
this.orderRepository = orderRepository;
}
public void placeOrder(Order order) {
// Business logic for placing an order
orderRepository.save(order);
}
}
Factory:工厂
命名惯例: 通常在实体名后加上Factory
,例如:OrderFactory.java
。
使用场景:
- 提供创建复杂对象的逻辑,封装对象创建的细节。
- 常用于创建复杂的领域对象或聚合。
特点:
- 封装对象创建逻辑。
- 提供创建对象的方法。
代码示例
public class OrderFactory {
public static Order createOrder(String orderId, Customer customer) {
return new Order(orderId, customer);
}
}
Aggregate:聚合
命名惯例: 通常使用聚合根实体名作为文件名,例如:OrderAggregate.java
。
使用场景:
- 表示一组相关的领域对象的集合,通过一个根实体(Aggregate Root)来进行管理和操作。
- 常用于表示复杂的业务逻辑和数据结构。
特点:
- 由多个领域对象组成。
- 通过根实体进行管理和操作。
代码示例
public class OrderAggregate {
private Order order;
private List<OrderItem> items;
public OrderAggregate(Order order) {
this.order = order;
this.items = new ArrayList<>();
}
public void addItem(OrderItem item) {
items.add(item);
}
public double calculateTotalPrice() {
return items.stream().mapToDouble(OrderItem::getPrice).sum();
}
// Getters and setters
}
转载自:https://juejin.cn/post/7377290806727852067