跳转到内容

领域服务

领域服务(Domain Service)用于封装不自然地属于实体或值对象的领域逻辑。它是无状态的,处理跨多个聚合或实体的业务规则。

领域服务具有以下特征:

  1. 无状态:不保存业务状态,只包含业务逻辑
  2. 操作多个对象:通常涉及多个实体或聚合
  3. 业务逻辑:包含重要的领域概念和规则
  4. 接口标记:实现 IDomainService 接口
using MiCake.DDD.Domain;
// 价格计算服务
public class PricingService : IDomainService
{
public Money CalculateTotalPrice(Order order, Customer customer)
{
var subtotal = order.GetSubtotal();
// 应用客户折扣
var discount = customer.GetDiscount();
var discountAmount = subtotal.Multiply(discount.AsDecimal());
// 计算税费
var taxRate = GetTaxRate(order.ShippingAddress);
var taxAmount = subtotal.Subtract(discountAmount).Multiply(taxRate);
// 计算运费
var shippingCost = CalculateShipping(order, customer);
return subtotal
.Subtract(discountAmount)
.Add(taxAmount)
.Add(shippingCost);
}
private decimal GetTaxRate(Address address)
{
// 根据地址计算税率
return address.Country == "CN" ? 0.13m : 0.20m;
}
private Money CalculateShipping(Order order, Customer customer)
{
if (customer.IsPremium)
return Money.Zero("CNY");
return new Money(10.00m, "CNY");
}
}
// 转账服务
public class TransferService : IDomainService
{
public void Transfer(BankAccount from, BankAccount to, Money amount)
{
if (from.Currency != amount.Currency || to.Currency != amount.Currency)
throw new DomainException("Currency mismatch");
if (from.Balance < amount)
throw new DomainException("Insufficient balance");
from.Withdraw(amount);
to.Deposit(amount);
}
}
// 领域服务:包含业务规则
public class OrderPricingService : IDomainService
{
// 计算订单价格的业务规则
public Money CalculateOrderTotal(Order order, List<Promotion> promotions)
{
var total = order.GetSubtotal();
foreach (var promotion in promotions.Where(p => p.AppliesTo(order)))
{
total = promotion.Apply(total);
}
return total;
}
}
// 应用服务:协调领域对象和基础设施
public class OrderApplicationService
{
private readonly IRepository<Order, int> _orderRepository;
private readonly IRepository<Customer, int> _customerRepository;
private readonly OrderPricingService _pricingService; // 使用领域服务
public async Task<OrderDto> CreateOrder(CreateOrderCommand command)
{
// 1. 加载聚合
var customer = await _customerRepository.FindAsync(command.CustomerId);
// 2. 创建订单
var order = Order.Create(customer.Id);
foreach (var item in command.Items)
{
order.AddItem(item.ProductId, item.Quantity, item.Price);
}
// 3. 使用领域服务计算价格
var total = _pricingService.CalculateOrderTotal(order, customer.GetActivePromotions());
order.SetTotalAmount(total);
// 4. 持久化
await _orderRepository.AddAsync(order);
await _orderRepository.SaveChangesAsync();
// 5. 返回 DTO
return MapToDto(order);
}
}
  1. 操作涉及多个聚合
public class OrderFulfillmentService : IDomainService
{
public bool CanFulfillOrder(Order order, List<Product> products)
{
// 检查多个产品的库存
foreach (var item in order.Items)
{
var product = products.First(p => p.Id == item.ProductId);
if (product.Stock < item.Quantity)
return false;
}
return true;
}
}
  1. 复杂的业务计算
public class ShippingCostCalculator : IDomainService
{
public Money Calculate(Order order, Address from, Address to)
{
var distance = CalculateDistance(from, to);
var weight = order.GetTotalWeight();
var dimensions = order.GetTotalDimensions();
// 复杂的运费计算逻辑
return CalculateShippingCost(distance, weight, dimensions);
}
}
  1. 业务规则验证
public class CreditCheckService : IDomainService
{
public bool CheckCredit(Customer customer, Money amount)
{
var creditLimit = customer.GetCreditLimit();
var outstandingBalance = customer.GetOutstandingBalance();
return outstandingBalance.Add(amount).Amount <= creditLimit.Amount;
}
}
  1. 属于单个实体的逻辑
// ❌ 不要:这应该是 Order 的方法
public class OrderService : IDomainService
{
public void AddItemToOrder(Order order, int productId, int quantity)
{
order.AddItem(productId, quantity);
}
}
// ✅ 正确:直接在 Order 中实现
public class Order : AggregateRoot<int>
{
public void AddItem(int productId, int quantity)
{
// 实现逻辑
}
}
  1. 纯技术性操作
// ❌ 不要:这是基础设施服务,不是领域服务
public class EmailSenderService : IDomainService
{
public void SendEmail(string to, string subject, string body)
{
// 发送邮件
}
}
// ✅ 正确:放在基础设施层
public interface IEmailService
{
Task SendEmailAsync(string to, string subject, string body);
}

领域服务通过依赖注入使用:

// 标记为作用域服务,自动注册
public class PricingService : IDomainService, IScopedService
{
private readonly ITaxRateProvider _taxRateProvider;
public PricingService(ITaxRateProvider taxRateProvider)
{
_taxRateProvider = taxRateProvider;
}
public Money CalculateTotal(Order order)
{
var subtotal = order.GetSubtotal();
var taxRate = _taxRateProvider.GetRate(order.ShippingAddress);
return subtotal.Multiply(1 + taxRate);
}
}
// 在应用服务中使用
public class OrderApplicationService
{
private readonly PricingService _pricingService;
public OrderApplicationService(PricingService pricingService)
{
_pricingService = pricingService;
}
public async Task ProcessOrder(int orderId)
{
var order = await _orderRepository.FindAsync(orderId);
var total = _pricingService.CalculateTotal(order);
order.SetTotal(total);
await _orderRepository.SaveChangesAsync();
}
}
// ✅ 正确 - 无状态
public class DiscountCalculator : IDomainService
{
public Money Calculate(Order order, Customer customer)
{
// 不保存任何状态
return order.GetSubtotal().Multiply(customer.DiscountRate);
}
}
// ❌ 错误 - 有状态
public class DiscountCalculator : IDomainService
{
private Order _currentOrder; // 不要保存状态
public void SetOrder(Order order)
{
_currentOrder = order;
}
}
public class OrderService : IDomainService
{
// ✅ 清晰的业务含义
public bool CanBeCancelled(Order order) { }
public Money CalculateTotalWithTax(Order order, Address address) { }
public bool MeetsMinimumOrderValue(Order order) { }
}
public class PricingService : IDomainService
{
private readonly ITaxRateProvider _taxRateProvider; // 接口
private readonly IShippingCalculator _shippingCalculator; // 接口
public PricingService(
ITaxRateProvider taxRateProvider,
IShippingCalculator shippingCalculator)
{
_taxRateProvider = taxRateProvider;
_shippingCalculator = shippingCalculator;
}
}
public class OrderPricingService : IDomainService, IScopedService
{
private readonly ITaxRateProvider _taxRateProvider;
private readonly IShippingCalculator _shippingCalculator;
public OrderPricingService(
ITaxRateProvider taxRateProvider,
IShippingCalculator shippingCalculator)
{
_taxRateProvider = taxRateProvider;
_shippingCalculator = shippingCalculator;
}
public OrderPricing CalculatePricing(Order order, Customer customer)
{
// 1. 商品小计
var subtotal = CalculateSubtotal(order);
// 2. 应用折扣
var discount = CalculateDiscount(subtotal, customer);
// 3. 计算税费
var taxAmount = CalculateTax(subtotal - discount, order.ShippingAddress);
// 4. 计算运费
var shippingCost = _shippingCalculator.Calculate(
order,
customer.ShippingAddress
);
return new OrderPricing
{
Subtotal = subtotal,
Discount = discount,
Tax = taxAmount,
Shipping = shippingCost,
Total = subtotal - discount + taxAmount + shippingCost
};
}
private Money CalculateSubtotal(Order order)
{
return order.Items
.Select(i => i.Price.Multiply(i.Quantity))
.Aggregate((a, b) => a.Add(b));
}
private Money CalculateDiscount(Money subtotal, Customer customer)
{
var discountRate = customer.GetDiscountRate();
return subtotal.Multiply(discountRate.AsDecimal());
}
private Money CalculateTax(Money amount, Address address)
{
var taxRate = _taxRateProvider.GetRate(address);
return amount.Multiply(taxRate);
}
}

领域服务用于封装不属于实体或值对象的业务逻辑:

  • 实现 IDomainService 接口
  • 保持无状态
  • 处理跨多个聚合的操作
  • 包含复杂的业务规则
  • 通过依赖注入使用

下一步: