当前位置: 首页 > news >正文

DDD-014:工厂(Factory)

DDD-014:工厂(Factory)

14.1 工厂的概念与职责

14.1.1 什么是工厂?

【原理】
工厂(Factory)是 DDD 中用于封装复杂对象创建逻辑的机制。当一个对象的创建过程过于复杂,不适合直接使用构造函数时,就需要使用工厂来封装创建过程。

工厂的核心职责:

  • 封装创建逻辑:隐藏复杂的对象组装过程
  • 保证有效性:确保创建出的对象始终处于有效状态
  • 表达意图:通过工厂方法名清晰表达创建的意图
  • 分离关注点:将创建逻辑与业务逻辑分离

14.1.2 工厂的职责边界

【代码示例】

// 工厂只负责创建,不负责业务逻辑// ✅ 工厂职责:创建对象publicclassOrderFactory{publicOrdercreateOrder(CustomerIdcustomerId,List<OrderItemInfo>items){// 创建和组装对象Orderorder=newOrder(OrderId.generate(),customerId);for(OrderItemInfoitem:items){order.addItem(item.getProductId(),item.getProductName(),item.getPrice(),item.getQuantity());}returnorder;}}// ❌ 工厂不应该包含业务逻辑publicclassOrderFactory{publicOrdercreateAndSubmitOrder(CustomerIdcustomerId,List<OrderItemInfo>items){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
http://www.gsyq.cn/news/1457061.html

相关文章:

  • 设计师正在消失?不,是“AI增强型设计师”正在诞生:基于172家企业的岗位能力图谱重构,含5级认证路径与真实项目交付SOP(绝密内参·首度解禁)
  • 仅限内部技术委员会解密:头部知识IP已用的AI播客灰度发布模型(含Latency<800ms实测数据)
  • STC15单片机双串口通信实战:手把手教你配置串口2(附完整代码)
  • 2026最新!8款论文降AI率工具实测合集,建议收藏(含免费版)
  • 库存告急怎么办?拥有大库存量的Inconel 718厂商推荐清单 - 品牌2026
  • 保姆级教程:在Ubuntu 20.04上为AirSim ROS节点添加自定义角速度控制接口
  • 2026年近期广东有实力的精密热流道供应商综合分析与推荐 - 2026年企业资讯
  • 【权威认证】工信部信创工作组推荐方案:AI工具与智能勋章融合的6层可信架构标准
  • 用Python复现AB3DMOT:200+FPS的3D目标跟踪,从KITTI点云数据开始
  • 千寻智能Spirit v1.6反超英伟达Cosmos 3,3个月融资近50亿背后有何秘诀?
  • OpenClaw从入门到应用——CLI:Dashboard
  • Memos数据库文件(.db)的另类玩法:不靠官方导出,用几行Python代码喂饱你的Obsidian Thino插件
  • 2026青少年防控镜片评测:星乐视4.0三效压轴/渐进多焦点镜片/眼轴控制镜片/碳晶A5膜镜片/离焦镜片/耐磨镜片/选择指南 - 优质品牌商家
  • 南京信息工程大学LaTeX论文模板终极指南:5步解决本科生毕业论文排版难题
  • # FIVEOS AI智能编程测试说明
  • 2026年新发布:武汉水冷冷凝器实力厂家全景解析与选型指南 - 2026年企业资讯
  • 【AI工具与内容系统整合实战指南】:20年架构师亲授5大避坑法则与3套落地模板
  • 欧洲议会弃Google选Qwant,隐私优先能否抗衡搜索巨头?
  • 终极指南:如何用Palmer Penguins数据集替代Iris进行数据科学教学
  • Proxmox VE安装踩坑实录:从镜像写入到网络配置,这5个错误千万别犯
  • 2026年 医用无机预涂板/重庆装配式无机预涂板/医疗无机预涂板/抗菌无机预涂板厂家推荐:洁净抗菌与绿色环保的首选品牌 - 品牌企业推荐师(官方)
  • 告别格式焦虑:我是如何用NUIST LaTeX模板拯救毕业论文的
  • Path of Building PoE2:流放之路2构建模拟器的技术架构深度解析
  • DIY感应加热器制作:双线并绕线圈与Mazzilli ZVS驱动器实战评测
  • 终极Suno-API音乐生成服务:从零构建完整的AI音乐创作平台 [特殊字符]
  • 20种传统密码设置方法
  • AI法律文书生成准确率为何卡在82.3%?基于37家律所实测数据的模型微调与规则引擎协同方案
  • FreeRTOS 手动移植教程(三):任务延时与时间管理——从裸机 delay 到 vTaskDelayUntil
  • 如何安全备份你的QQ空间数字记忆:GetQzonehistory完整指南
  • 2026年6月永州职业高中选型技术推荐与实测盘点:永州中等专业学校/永州民办中专学校/永州职业技术学校/优选推荐 - 优质品牌商家