文章目录
- 引言:DDD战术模式的重要性
- 一、DDD中的工厂模式
- 1.1 工厂模式的核心概念
- 1.2 工厂模式的三种实现方式
- 1.2.1 简单工厂方法
- 1.2.2 工厂类
- 1.2.3 抽象工厂模式
- 1.3 工厂模式的适用场景
- 1.4 实际案例:电商订单系统
- 二、表意接口模式
- 2.1 表意接口
- 2.2 表意接口的实现要点
- 2.2.1 命名规范
- 2.2.2 方法设计
- 2.3 表意接口的优势
- 2.4 实际案例:库存管理系统
- 三、工厂模式与表意接口的协同应用
- 3.1 结合使用的优势
- 3.2 综合案例:用户注册系统
- 3.3 反模式与常见错误
- 四、总结
引言:DDD战术模式的重要性
- 在领域驱动设计(DDD)中,战术模式是实现领域模型的关键工具。今天我们将深入探讨两个核心模式:工厂模式(Factory)和表意接口(Intention-Revealing Interfaces)模式。这些模式不仅能提升代码质量,还能使领域逻辑更加清晰明确。
一、DDD中的工厂模式
1.1 工厂模式的核心概念
工厂模式在DDD中负责封装复杂对象的创建逻辑,其主要目的是:
- 保持领域对象的完整性
- 隐藏复杂的构造逻辑
- 提供一致的创建接口
- 避免领域模型泄露构造细节
1.2 工厂模式的三种实现方式
1.2.1 简单工厂方法
public class Order {public static Order createOrder(Customer customer, List<OrderItem> items) {Order order = new Order();order.setCustomer(customer);order.setItems(items);order.setStatus(OrderStatus.CREATED);order.setCreatedDate(LocalDateTime.now());return order;}
}
1.2.2 工厂类
public class PaymentFactory {public Payment createCreditCardPayment(BigDecimal amount, CreditCard card) {CreditCardPayment payment = new CreditCardPayment();payment.setAmount(amount);payment.setCard(card);payment.setPaymentDate(LocalDateTime.now());return payment;}public Payment createBankTransferPayment(BigDecimal amount, BankAccount account) {// 实现细节...}
}
1.2.3 抽象工厂模式
public interface ShippingProviderFactory {ShippingProvider createDomesticProvider();ShippingProvider createInternationalProvider();
}public class FedexShippingFactory implements ShippingProviderFactory {// 具体实现...
}
1.3 工厂模式的适用场景
- 复杂对象构造:当对象构造涉及多个步骤或复杂逻辑时
- 聚合根创建:确保聚合根及其内部实体的一致性
- 多态对象创建:需要根据条件创建不同类型的对象
- 重建持久化对象:从数据库重建领域对象时
1.4 实际案例:电商订单系统
public class OrderFactory {public Order createOrder(Customer customer, List<Product> products, Discount discount) {// 验证业务规则if (customer.isBlocked()) {throw new CustomerBlockedException();}// 创建订单聚合根Order order = new Order();order.setOrderNumber(generateOrderNumber());order.setCustomer(customer);order.setStatus(OrderStatus.PENDING);// 创建订单项List<OrderItem> items = products.stream().map(p -> createOrderItem(p, discount)).collect(Collectors.toList());order.setItems(items);// 计算总价order.calculateTotal();return order;}private OrderItem createOrderItem(Product product, Discount discount) {// 实现细节...}
}
二、表意接口模式
2.1 表意接口
表意接口(Intention-Revealing Interfaces)是指通过接口名称和方法签名就能清晰表达其意图和行为的接口设计方式。其核心原则是:
- 自描述性:无需查看实现就能理解其目的
- 领域一致性:使用领域专家熟悉的术语
- 行为明确:方法名准确反映其行为
2.2 表意接口的实现要点
2.2.1 命名规范
- 不良示例:
public interface OrderService {void process(Object data);
}
- 良好示例:
public interface OrderProcessing {OrderConfirmation placeOrder(ShoppingCart cart);void cancelOrder(OrderNumber orderNumber);OrderStatus checkOrderStatus(OrderNumber orderNumber);
}
2.2.2 方法设计
- 不良示例:
public class Account {public void update(BigDecimal amount) {// 实现细节...}
}
- 良好示例:
public class BankAccount {public void deposit(Money amount) {// 存款操作}public void withdraw(Money amount) throws InsufficientFundsException {// 取款操作}public void transfer(Money amount, BankAccount target) {// 转账操作}
}
2.3 表意接口的优势
- 提高代码可读性:减少理解代码所需的时间
- 降低认知负荷:开发者可以快速理解领域逻辑
- 减少文档依赖:代码自身就是最好的文档
- 促进统一语言:强化团队对领域术语的使用
2.4 实际案例:库存管理系统
- 不良设计:
public class Inventory {public void adjust(int id, int qty) {// 实现细节...}
}
- 表意接口设计:
public class InventoryManagement {public StockLevel receiveStock(ProductId product, Quantity quantity) {// 入库操作}public StockLevel reserveStock(ProductId product, Quantity quantity) throws OutOfStockException {// 预留库存}public void fulfillReservation(ReservationId reservation) {// 完成预留}public StockReport generateStockReport(ProductCategory category) {// 生成库存报告}
}
三、工厂模式与表意接口的协同应用
3.1 结合使用的优势
- 当工厂模式与表意接口结合使用时,可以产生更强大的效果:
- 清晰的创建语义:工厂方法名明确表达创建意图
- 一致的构造约束:通过工厂确保对象始终有效
- 简化的客户端代码:调用方只需关注"做什么"而非"怎么做"
3.2 综合案例:用户注册系统
public interface UserRegistration {User registerNewCustomer(CustomerRegistrationForm form);User registerAdminUser(AdminRegistrationRequest request);User inviteTeamMember(TeamMemberInvitation invitation);
}public class UserFactoryImpl implements UserRegistration {public User registerNewCustomer(CustomerRegistrationForm form) {// 验证表单数据validateRegistrationForm(form);// 创建用户聚合User user = new User();user.setUsername(form.getEmail());user.setPassword(encryptPassword(form.getPassword()));user.setRoles(Set.of(Role.CUSTOMER));user.setStatus(UserStatus.ACTIVE);// 创建客户实体Customer customer = new Customer();customer.setUser(user);customer.setPersonalDetails(form.getPersonalDetails());user.setCustomerProfile(customer);return user;}// 其他方法实现...
}
3.3 反模式与常见错误
-
通用工厂:避免创建过于通用的工厂接口
// 不良设计 public interface GenericFactory {Object create(String type); }
-
模糊命名:工厂方法名应明确表达创建的对象的类型和意图
// 不良设计 public class PaymentCreator {public Payment make(String type) {// 实现细节...} }// 良好设计 public class PaymentMethodFactory {public CreditCardPayment createCreditCardPayment(CardDetails card) {// 实现细节...} }
-
泄露实现细节:接口不应暴露内部实现机制
// 不良设计 public interface OrderService {void saveToDatabase(Order order); }// 良好设计 public interface OrderRepository {void save(Order order); }
四、总结
- 工厂模式和表意接口模式是DDD战术设计中相辅相成的两个重要模式。工厂模式通过封装对象创建逻辑来保证领域对象的完整性和一致性,而表意接口模式则通过清晰的命名和设计使领域意图更加明确。
在实际应用中,我们应该:
- 为复杂对象创建专门的工厂,特别是聚合根
- 使用领域术语命名工厂方法和接口
- 确保接口名称准确反映其行为和意图
- 通过工厂执行必要的业务规则验证
- 保持接口的简洁性和专注性