DDD-014:工厂(Factory)14.1 工厂的概念与职责14.1.1 什么是工厂?【原理】工厂(Factory)是 DDD 中用于封装复杂对象创建逻辑的机制。当一个对象的创建过程过于复杂,不适合直接使用构造函数时,就需要使用工厂来封装创建过程。工厂的核心职责:封装创建逻辑:隐藏复杂的对象组装过程保证有效性:确保创建出的对象始终处于有效状态表达意图:通过工厂方法名清晰表达创建的意图分离关注点:将创建逻辑与业务逻辑分离14.1.2 工厂的职责边界【代码示例】// 工厂只负责创建,不负责业务逻辑// ✅ 工厂职责:创建对象publicclassOrderFactory{publicOrdercreateOrder(CustomerIdcustomerId,ListOrderItemInfoitems){// 创建和组装对象Orderorder=newOrder(OrderId.generate(),customerId);for(OrderItemInfoitem:items){order.addItem(item.getProductId(),item.getProductName(),item.getPrice(),item.getQuantity());}returnorder;}}// ❌ 工厂不应该包含业务逻辑publicclassOrderFactory{publicOrdercreateAndSubmitOrder(CustomerIdcustomerId,ListOrderItemInfoitems){Orderorder=newOrder(OrderId.generate(),customerId);order.submit();// 业务逻辑,不应该在工厂order.pay(payment);// 业务逻辑,不应该在工厂returnorder;}}14.2 工厂的使用场景14.2.1 需要使用工厂的场景【历史架构问题】// ❌ 传统做法:复杂构造逻辑散落各处@ServicepublicclassOrderService{publicOrdercreateOrder(CreateOrderRequestrequest){// 大量构造逻辑散落在Service中Orderorder=newOrder();order.setId(UUID.randomUUID().toString());order.setCustomerId(request.getCustomerId());order.setStatus("DRAFT");order.setCreatedAt(newDate());order.setItems(newArrayList());order.setTotalAmount(BigDecimal.ZERO);for(OrderItemRequestitemReq:request.getItems()){OrderItemitem=newOrderItem();item.setId(UUID.randomUUID().toString());item.setProductId(itemReq.getProductId());item.setProductName(itemReq.getProductName());item.setPrice(itemReq.getPrice());item.setQuantity(itemReq.getQuantity());order.getItems().add(item);order.setTotalAmount(order.getTotalAmount().add(itemReq.getPrice().multiply(newBigDecimal(itemReq.getQuantity()))));}// 问题:// 1. 构造逻辑复杂,散落在Service中// 2. 容易遗漏必要的初始化// 3. 代码重复,多处创建逻辑// 4. 无法保证对象有效性returnorder;}}【DDD 如何解决】// ✅ DDD工厂:封装创建逻辑publicclassOrder{// 私有构造函数,防止外部直接实例化privateOrder(OrderIdid,CustomerIdcustomerId){this.id=id;this.customerId=customerId;this.status=OrderStatus.DRAFT;this.items=newArrayList();this.totalAmount=Money.ZERO;this.createdAt=LocalDateTime.now();}// 静态工厂方法:表达创建意图publicstaticOrdercreate(CustomerIdcustomerId){Objects.requireNonNull(customerId,"客户ID不能为空");Orderorder=newOrder(OrderId.generate(),customerId);order.registerEvent(newOrderCreatedEvent(order.id,customerId));returnorder;}// 静态工厂方法:从购物车创建publicstaticOrdercreateFromCart(CustomerIdcustomerId,ShoppingCartcart){Objects.requireNonNull(customerId,"客户ID不能为空");Objects.requireNonNull(cart,"购物车不能为空");Orderorder=newOrder(OrderId.generate(),customerId);for(CartItemcartItem:cart.getItems()){order.addItem(cartItem.getProductId(),cartItem.getProductName(),cartItem.getPrice(),cartItem.getQuantity());}order.registerEvent(newOrderCreatedFromCartEvent(order.id,customerId,cart.getId()));returnorder;}}14.2.2 不需要使用工厂的场景// 简单对象:直接使用构造函数Moneyprice=Money.of("99.99");CustomerIdcustomerId=CustomerId.of("C001");OrderIdorderId=OrderId.generate();// 值对象:直接使用构造函数或静态工厂ShippingAddressaddress=newShippingAddress("上海市","浦东新区","张江镇","祖冲之路1234号","张三","13800138000");14.3 工厂 vs 构造函数14.3.1 对比分析维度构造函数工厂方法工厂类命名与类名相同自定义名称自定义名称创建逻辑简单初始化中等复杂度高复杂度返回类型固定为当前类可返回子类可返回任意类型多种创建方式需要重载方法名区分方法名区分位置类内部类内部或外部独立类适用场景简单对象中等复杂对象复杂聚合14.3.2 何时选择【代码示例】// 场景1:简单对象 → 构造函数Moneyprice=newMoney(newBigDecimal("99.99"),Currency.getInstance("CNY"));// 场景2:有语义的创建 → 静态工厂方法publicclassOrder{privateOrder(OrderIdid,CustomerIdcustomerId){...}publicstaticOrdercreate(CustomerIdcustomerId){...}publicstaticOrderreconstruct(OrderIdid,...){...}// 重建}// 场景3:复杂组装 → 工厂类publicclassOrderFactory{publicOrdercreateOrder(CreateOrderCommandcommand){// 复杂的组装逻辑}}// 场景4:需要外部依赖 → 工厂类 + 依赖注入@ServicepublicclassOrderFactory{@AutowiredprivatePricingServicepricingService;publicOrdercreateOrder(CreateOrderCommandcommand){// 可以使用定价服务}}14.4 工厂 vs 依赖注入14.4.1 区别与配合【对比分析】维度工厂依赖注入(DI)目的创建业务对象注入服务依赖创建时机业务驱动容器启动时创建对象领域对象服务/组件生命周期每次调用创建新实例通常单例状态有状态(业务数据)无状态【代码示例】// ✅ 正确:工厂创建领域对象,DI注入服务@ServicepublicclassOrderFactory{// DI注入服务依赖privatefinalIdentityGeneratoridGenerator;privatefinalPricingServicepricingService;publicOrderFactory(IdentityGeneratoridGenerator,PricingServicepricingService){this.idGenerator=idGenerator;this.pricingService=pricingService;}// 工厂方法创建领域对象publicOrdercreateOrder(CreateOrderCommandcommand){OrderIdid=idGenerator.generateOrderId();CustomerIdcustomerId=Custo
DDD-014:工厂(Factory)
发布时间:2026/6/4 1:09:43
DDD-014:工厂(Factory)14.1 工厂的概念与职责14.1.1 什么是工厂?【原理】工厂(Factory)是 DDD 中用于封装复杂对象创建逻辑的机制。当一个对象的创建过程过于复杂,不适合直接使用构造函数时,就需要使用工厂来封装创建过程。工厂的核心职责:封装创建逻辑:隐藏复杂的对象组装过程保证有效性:确保创建出的对象始终处于有效状态表达意图:通过工厂方法名清晰表达创建的意图分离关注点:将创建逻辑与业务逻辑分离14.1.2 工厂的职责边界【代码示例】// 工厂只负责创建,不负责业务逻辑// ✅ 工厂职责:创建对象publicclassOrderFactory{publicOrdercreateOrder(CustomerIdcustomerId,ListOrderItemInfoitems){// 创建和组装对象Orderorder=newOrder(OrderId.generate(),customerId);for(OrderItemInfoitem:items){order.addItem(item.getProductId(),item.getProductName(),item.getPrice(),item.getQuantity());}returnorder;}}// ❌ 工厂不应该包含业务逻辑publicclassOrderFactory{publicOrdercreateAndSubmitOrder(CustomerIdcustomerId,ListOrderItemInfoitems){Orderorder=newOrder(OrderId.generate(),customerId);order.submit();// 业务逻辑,不应该在工厂order.pay(payment);// 业务逻辑,不应该在工厂returnorder;}}14.2 工厂的使用场景14.2.1 需要使用工厂的场景【历史架构问题】// ❌ 传统做法:复杂构造逻辑散落各处@ServicepublicclassOrderService{publicOrdercreateOrder(CreateOrderRequestrequest){// 大量构造逻辑散落在Service中Orderorder=newOrder();order.setId(UUID.randomUUID().toString());order.setCustomerId(request.getCustomerId());order.setStatus("DRAFT");order.setCreatedAt(newDate());order.setItems(newArrayList());order.setTotalAmount(BigDecimal.ZERO);for(OrderItemRequestitemReq:request.getItems()){OrderItemitem=newOrderItem();item.setId(UUID.randomUUID().toString());item.setProductId(itemReq.getProductId());item.setProductName(itemReq.getProductName());item.setPrice(itemReq.getPrice());item.setQuantity(itemReq.getQuantity());order.getItems().add(item);order.setTotalAmount(order.getTotalAmount().add(itemReq.getPrice().multiply(newBigDecimal(itemReq.getQuantity()))));}// 问题:// 1. 构造逻辑复杂,散落在Service中// 2. 容易遗漏必要的初始化// 3. 代码重复,多处创建逻辑// 4. 无法保证对象有效性returnorder;}}【DDD 如何解决】// ✅ DDD工厂:封装创建逻辑publicclassOrder{// 私有构造函数,防止外部直接实例化privateOrder(OrderIdid,CustomerIdcustomerId){this.id=id;this.customerId=customerId;this.status=OrderStatus.DRAFT;this.items=newArrayList();this.totalAmount=Money.ZERO;this.createdAt=LocalDateTime.now();}// 静态工厂方法:表达创建意图publicstaticOrdercreate(CustomerIdcustomerId){Objects.requireNonNull(customerId,"客户ID不能为空");Orderorder=newOrder(OrderId.generate(),customerId);order.registerEvent(newOrderCreatedEvent(order.id,customerId));returnorder;}// 静态工厂方法:从购物车创建publicstaticOrdercreateFromCart(CustomerIdcustomerId,ShoppingCartcart){Objects.requireNonNull(customerId,"客户ID不能为空");Objects.requireNonNull(cart,"购物车不能为空");Orderorder=newOrder(OrderId.generate(),customerId);for(CartItemcartItem:cart.getItems()){order.addItem(cartItem.getProductId(),cartItem.getProductName(),cartItem.getPrice(),cartItem.getQuantity());}order.registerEvent(newOrderCreatedFromCartEvent(order.id,customerId,cart.getId()));returnorder;}}14.2.2 不需要使用工厂的场景// 简单对象:直接使用构造函数Moneyprice=Money.of("99.99");CustomerIdcustomerId=CustomerId.of("C001");OrderIdorderId=OrderId.generate();// 值对象:直接使用构造函数或静态工厂ShippingAddressaddress=newShippingAddress("上海市","浦东新区","张江镇","祖冲之路1234号","张三","13800138000");14.3 工厂 vs 构造函数14.3.1 对比分析维度构造函数工厂方法工厂类命名与类名相同自定义名称自定义名称创建逻辑简单初始化中等复杂度高复杂度返回类型固定为当前类可返回子类可返回任意类型多种创建方式需要重载方法名区分方法名区分位置类内部类内部或外部独立类适用场景简单对象中等复杂对象复杂聚合14.3.2 何时选择【代码示例】// 场景1:简单对象 → 构造函数Moneyprice=newMoney(newBigDecimal("99.99"),Currency.getInstance("CNY"));// 场景2:有语义的创建 → 静态工厂方法publicclassOrder{privateOrder(OrderIdid,CustomerIdcustomerId){...}publicstaticOrdercreate(CustomerIdcustomerId){...}publicstaticOrderreconstruct(OrderIdid,...){...}// 重建}// 场景3:复杂组装 → 工厂类publicclassOrderFactory{publicOrdercreateOrder(CreateOrderCommandcommand){// 复杂的组装逻辑}}// 场景4:需要外部依赖 → 工厂类 + 依赖注入@ServicepublicclassOrderFactory{@AutowiredprivatePricingServicepricingService;publicOrdercreateOrder(CreateOrderCommandcommand){// 可以使用定价服务}}14.4 工厂 vs 依赖注入14.4.1 区别与配合【对比分析】维度工厂依赖注入(DI)目的创建业务对象注入服务依赖创建时机业务驱动容器启动时创建对象领域对象服务/组件生命周期每次调用创建新实例通常单例状态有状态(业务数据)无状态【代码示例】// ✅ 正确:工厂创建领域对象,DI注入服务@ServicepublicclassOrderFactory{// DI注入服务依赖privatefinalIdentityGeneratoridGenerator;privatefinalPricingServicepricingService;publicOrderFactory(IdentityGeneratoridGenerator,PricingServicepricingService){this.idGenerator=idGenerator;this.pricingService=pricingService;}// 工厂方法创建领域对象publicOrdercreateOrder(CreateOrderCommandcommand){OrderIdid=idGenerator.generateOrderId();CustomerIdcustomerId=Custo