在领域驱动设计(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 }