在上一篇文章当中,我们简单讲解了DDD架构的部分概念,现在我们讲解一下大部分的核心概念
注意 每个公司的DDD架构的实现可能不大一样,也就是在架构方面 ,但是总体思想仍然是一致的
实体(Entity)
概念
实体是在相同限界上下文中具有唯一标识的领域模型,可变,通过标识判断同一性。例如用户、订单等,关键在于它们的身份(ID)而非属性值。
简单而言,就是实体类,但是需要注意一点,实体类中应具备当前类的服务, 也就是充血模型中服务聚合
举例
// Java示例:Order实体
public class Order {
private final String orderId; // 唯一标识
private String customerId;
private OrderStatus status;
// 构造函数、Getter省略
public Order(String orderId, String customerId) {
this.orderId = orderId;
this.customerId = customerId;
this.status = OrderStatus.NEW;
}
// 领域行为:支付订单
public void pay() {
if (status != OrderStatus.NEW) {
throw new IllegalStateException("订单不能支付");
}
this.status = OrderStatus.PAID;
}
// ... 其他业务逻辑方法
}
值对象(Value Object)
概念
一种没有唯一标识、通过属性值判断相等性的领域模型 ,他跟实体的区别就是,实体一般是有周期性的,会在业务流程中被追踪,值对象更多的是一种标识
举例
// Java示例:Money值对象
public class Money {
private final BigDecimal amount;
private final String currency; // 币种
public Money(BigDecimal amount, String currency) {
if (amount.signum() < 0) throw new IllegalArgumentException("金额必须非负");
this.amount = amount;
this.currency = currency;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Money)) return false;
Money other = (Money) o;
return amount.equals(other.amount) && currency.equals(other.currency);
}
@Override
public int hashCode() {
return Objects.hash(amount, currency);
}
// 领域行为:累加金额
public Money add(Money other) {
if (!this.currency.equals(other.currency)) {
throw new IllegalArgumentException("币种不一致");
}
return new Money(this.amount.add(other.amount), this.currency);
}
}
聚合根(Aggregate Root)
概念
聚合是一组相关实体和值对象的集合,在业务上表达统一意义,并在其内部保证一致性。聚合中有一个聚合根(Aggregate Root),它是聚合的唯一对外入口。
聚合根是聚合中最核心的实体,其他实体和值对象都从属于它。每个聚合必须有且只有一个聚合根(聚合也可只包含单一根实体)。聚合根在持久化和查找时发挥作用。
简单而言,就是将实体和值对象疯转在一起(注意,是有关联的实体和值对象)
举例
// Java示例:Order聚合根与子对象
public class Order {
private final String orderId;
private final List<OrderItem> items = new ArrayList<>(); // 聚合内实体
private OrderStatus status;
public Order(String orderId) {
this.orderId = orderId;
this.status = OrderStatus.NEW;
}
public void addItem(String productId, int qty) {
if (status != OrderStatus.NEW) {
throw new IllegalStateException("已提交订单不可添加商品");
}
items.add(new OrderItem(productId, qty));
}
// 计算订单总价
public Money totalPrice() {
Money total = new Money(BigDecimal.ZERO, "CNY");
for (OrderItem item : items) {
total = total.add(item.getPrice());
}
return total;
}
}
public class OrderItem {
private final String productId;
private final int quantity;
private final Money price; // 值对象
public OrderItem(String productId, int quantity) {
this.productId = productId;
this.quantity = quantity;
this.price = fetchPriceFromCatalog(productId).multiply(quantity);
}
public Money getPrice() { return price; }
}
仓储(Repository)
概念
储是以持久化聚合根为职责的类或接口。它为领域层提供查找和持久化功能,屏蔽底层存储(数据库/ORM)实现差异。
一般来说,仓储是暴露给外界的接口,用来访问聚合根的数据
举例
// Java示例:Order仓储接口
public interface OrderRepository {
Order findById(String orderId);
void save(Order order);
}
领域服务(Domain Service)
概念
领域服务是领域层的无状态服务,用于封装不属于单一实体或值对象的业务逻辑。通常是跨实体或跨聚合的操作,如复杂计算、领域算法等
一般来说就是mvc中的service,需要多个实体之间的相互调用的时候就会使用到
举例
// Java示例:跨账户转账领域服务
public class TransferService {
public void transfer(Account from, Account to, Money amount) {
from.withdraw(amount);
to.deposit(amount);
}
}
应用服务(Application Service)
概念
应用服务位于应用层,用于组织和协调领域对象以完成特定业务用例。它为上层(如UI)提供接口,负责调用领域模型、控制事务并返回结果。
举例
// Java示例:订单应用服务
public class OrderApplicationService {
private final OrderRepository orderRepo;
public OrderApplicationService(OrderRepository repo) {
this.orderRepo = repo;
}
public String createOrder(String customerId, List<OrderItem> items) {
// 创建聚合根并执行业务操作
Order order = new Order(UUID.randomUUID().toString());
for (OrderItem item : items) {
order.addItem(item.getProductId(), item.getQuantity());
}
orderRepo.save(order);
return order.getOrderId();
}
}
应用服务和领域服务的关系
领域服务一般指的是实体类之间的相互调用,属于业务中的逻辑调用,而应用服务是对领域服务的调用

领域事件(Domain Event)
概念
领域事件是在业务领域中已经发生的关键事实或状态变化。它反映领域模型中某个实体或聚合根的重要变化,并可通知系统其他部分。于解耦和记录业务流程中的重要事件。例如订单"已支付"(OrderPaid)、库存"低于安全线"等。领域事件可以触发其他处理(如发送通知、更新查询模型等)。
工厂(Factory)
概念
工厂是负责构建领域模型(实体或值对象)的类或方法
。它封装对象创建的复杂逻辑,如参数验证、赋予默认值等。
举例
// C#示例:Order工厂
public static class OrderFactory {
public static Order CreateOrder(string customerId, IEnumerable<OrderItem> items) {
var order = new Order(Guid.NewGuid().ToString());
foreach (var item in items) {
order.AddItem(item.ProductId, item.Quantity);
}
return order;
}
}
界限上下文
概念
限界上下文是DDD的核心战略模式,定义了模型的边界。每个上下文使用一致的术语和规则,不同上下文可以有相同名词但含义不同(模型在上下文内保持一致性)。在大型系统中,不同子域有不同模型时,需要划分限界上下文。例如电商系统中,订单、库存、支付分别属于不同限界上下文,各自处理相应领域。 也就是每个业务可以任务是一个上下文,一个上下文中的语法应该是一致的,对外暴露api接口即可

上下文映射(Context Mapping)
概念
定义: 上下文映射是描述限界上下文之间关系的模式集合,通常用图示表示。常见模式包括合作(Partnership)、共享内核(Shared Kernel)、客户-供应方(Customer-Supplier)、遵奉者(Conformist)、反腐层(ACL)、开放主机服务(OHS)等。
反腐层(Anti-Corruption Layer)
概念
在不同限界上下文或系统之间构建的适配层,用于翻译和隔离模型。它将一个系统的请求转换为本系统的模型,防止外部模型污染本领域模型。有点类似于适配器,来作为防腐服务。 就是一个业务需要另外的业务时,应只暴露本身上下文的模型,而不是使用对面的领域对象。
事件风暴(Event Storming)
概念
事件风暴是一种以工作坊形式进行的协作领域建模方法,由 Alberto Brandolini 提出。参与者(开发者和领域专家)通过贴便利贴标记领域事件、命令、聚合等元素,快速探索和分析复杂业务流程。