戴老师的博客 - ddd
type: channel
link: https://www.tushu.info/tag/ddd/
items: 一文读懂：领域驱动设计DDD
items: DDD介绍
items: DDD接口层介绍
items: DDD应用层和领域层的区别
items: DDD中的Assembler（装配器）介绍
items: DDD中Infrastructure（基础设施层）介绍

一文读懂：领域驱动设计DDD
type: item
date: 2026-07-07T08:37:03+00:00
description: 前言领域驱动设计（Domain-Driven Design，简称 DDD）近年来备受关注，尤其是随着 2B 业务和 SaaS 模式的兴起。然而，不少开发者在阅读 Eric Evans 的《领域驱动设计》或 Vaughn Vernon 的《实现领域驱动设计》后，常感到内容过于抽象，难以落地。本文将在介绍 DDD 基本概念的同时，通过一个虚拟的公司和项目场景，详细介绍领域驱动设计的落地实践。什么是领域我习惯将领域描述为财务领域、人力领域、房地产领域、金融领域等。在领域内，各种业务规则与业务知识盛行。如何有效把控规则的变化、应对复杂知识？有一个关键的四字词语：分而治之。分治法在很多场景下体现了其强大的作用力。领域本身很大很复杂，那就拆分，得到更小的领域，也即子域。如同递归调用一般，将一个复杂问题拆分单独求解，最终将解汇总得到复杂问题解。怎么拆？拆成什么样合适？依据什么拆？这些在领域驱动设计中都有了一套答案。虽然领域驱动设计不是银弹，但可以说是一套极好的系统方法论，或称为架构设计的方法论。领域驱动设计常以战略设计与战术设计来将整个领域展现得淋漓尽致，其作用范围既面向业务也面向技术。从战略角度的整体性（个人更喜欢称其为上帝视角）去规划系统、划分领域；而从战术角度则从技术层面来指导我们该如何去设计。为什么需要建立一个领域模型领域驱动设计告诉我们，在通过软件实现一个业务系统时，建立一个领域模型是非常重要和必要的，因为领域模型具有以下特点：抽象与边界：领域模型是对具有某个边界的领域的一个抽象，反映了领域内用户业务需求的本质；领域模型是有边界的，只反映了我们在领域内所关注的部分。业务无关技术：领域模型只反映业务，和任何技术实现无关；领域模型不仅能反映领域中的一些实体概念（如货物、书本、应聘记录、地址等），还能反映领域中的一些过程概念（如资金转账等）。逻辑集中：领域模型确保了我们的软件的业务逻辑都在一个模型中，都在一个地方；这样对提高软件的可维护性、业务可理解性以及可重用性方面都有很好的帮助。知识转化：领域模型能够帮助开发人员相对平滑地将领域知识转化为软件构造。全程贯穿：领域模型贯穿软件分析、设计，以及开发的整个过程；领域专家、设计人员、开发人员通过领域模型进行交流，彼此共享知识与信息；因为大家面向的都是同一个模型，所以可以防止需求走样，可以让软件设计开发人员做出来的软件真正满足需求。共同构建：要建立正确的领域模型并不简单，需要领域专家、设计、开发人员积极沟通共同努力，然后才能使大家对领域的认识不断深入，从而不断细化和完善领域模型。表达方式：为了让领域模型看得见，我们需要用一些方法来表示它；图是表达领域模型最常用的方式，但不是唯一的表达方式，代码或文字描述也能表达领域模型。核心价值：领域模型是整个软件的核心，是软件中最有价值和最具竞争力的部分；设计足够精良且符合业务需求的领域模型能够更快速地响应需求变化。领域通用语言（Ubiquitous Language）我们认识到由软件专家和领域专家通力合作开发出一个领域的模型是绝对需要的，但是，那种方法通常会由于一些基础交流的障碍而存在难点。开发人员满脑子都是类、方法、算法、模式、架构等等，总是想将实际生活中的概念和程序工件进行对应。他们希望看到要建立哪些对象类，要如何对对象类之间的关系建模。他们会习惯按照封装、继承、多态等面向对象编程中的概念去思考，会随时随地这样交谈，这对他们来说太正常不过了。但是领域专家通常对此一无所知，他们对软件类库、框架、持久化甚至数据库没有什么概念。他们只了解他们特有的领域专业技能。比如，在空中交通监控样例中，领域专家知道飞机、路线、海拔、经度、纬度，知道飞机偏离了正常路线，知道飞机的发射。他们用他们自己的术语讨论这些事情，有时这对于外行来说很难直接理解。如果一个人说了什么事情，其他的人不能理解，或者更糟的是错误理解成其他事情，又有什么机会来保证项目成功呢？在交流的过程中，需要做翻译才能让其他的人理解这些概念。开发人员可能会努力使用外行人的语言来解析一些设计模式，但这并不一定都能成功奏效。领域专家也可能会创建一种新的行话以努力表达他们的这些想法。在这个痛苦的交流过程中，这种类型的翻译并不能对知识的构建过程产生帮助。领域驱动设计的一个核心的原则是使用一种基于模型的语言。因为模型是软件满足领域的共同点，它很适合作为这种通用语言的构造基础。使用模型作为语言的核心骨架，要求团队在进行所有的交流时都使用一致的语言，在代码中也是这样。在共享知识和推敲模型时，团队会使用演讲、文字和图形。这里需要确保团队使用的语言在所有的交流形式中看上去都是一致的，这种语言被称为“通用语言（Ubiquitous Language）”。通用语言应该在建模过程中广泛尝试以推动软件专家和领域专家之间的沟通，从而发现要…

DDD介绍
type: item
date: 2026-07-07T08:33:20+00:00
description: DDD（领域驱动设计）全面介绍领域驱动设计（Domain-Driven Design，简称 DDD），是由埃里克·埃文斯（Eric Evans）在 2003 年出版的《领域驱动设计：软件核心复杂性应对之道》中提出的一种软件设计方法论。其核心思想是让软件设计与业务领域紧密对齐，通过聚焦业务核心逻辑、梳理领域概念，解决复杂业务系统的设计难题，避免代码与业务脱节及后期维护成本高昂的问题。一、DDD 的核心目标DDD 并非一套固定的“编码规范”，而是一种“设计思想”。其核心目标可概括为以下三点：降低复杂性：将复杂的业务系统拆解为更小、更易理解的“领域单元”。每个单元聚焦特定业务场景，避免整体系统陷入混沌。对齐业务与技术：让开发人员、产品经理、业务专家使用统一的“领域语言”沟通（避免技术侧说“接口”、业务侧说“流程”的认知偏差），确保软件实现真正满足业务需求。提升系统可维护性：业务逻辑集中在“领域层”，与技术框架（如数据库、API 层）解耦。后续业务变更时，只需修改领域层，无需大面积重构技术代码。二、DDD 的核心概念DDD 通过一系列抽象概念梳理业务逻辑，这些概念是理解 DDD 的基础，可分为“领域基础概念”和“设计模式概念”两类。1. 领域基础概念（1）领域（Domain）与子领域（Subdomain）领域：指软件要解决的“业务范围”，例如“电商领域”、“物流领域”、“金融支付领域”。子领域：将一个大领域拆解为更小的、聚焦单一业务方向的单元。例如“电商领域”可拆分为：核心子领域：订单管理（业务核心，直接决定业务价值）；支撑子领域：用户管理、商品管理（为核心服务，需自主开发）；通用子领域：日志、权限、通知（非业务专属，可复用现有组件或第三方服务）。（2）领域模型（Domain Model）领域模型是对业务领域中“概念、规则、流程”的抽象表达，不是数据库表的映射，而是业务逻辑的载体。例如“订单领域模型”会包含“订单状态流转规则（待支付→已支付→已发货）”、“订单金额计算逻辑（商品价 + 运费 - 优惠券）”等核心业务逻辑。（3）限界上下文（Bounded Context）DDD 中最关键的概念之一，指“一个边界，边界内的领域模型具有统一的语义（即领域语言），边界外的模型无需强关联”。作用：解决“同一概念在不同业务场景下含义不同”的问题。例如“用户”在“订单上下文”中只需“用户 ID、收货地址”，在“用户中心上下文”中则需要“手机号、密码、实名认证信息”——两个上下文的“用户模型”可独立设计，避免冗余。示例：电商系统的限界上下文可划分为“订单上下文”、“商品上下文”、“支付上下文”、“物流上下文”。2. 设计模式概念DDD 提供了具体的模式来落地领域模型，核心模式包括：概念定义与作用示例（电商订单场景）实体（Entity）具有唯一标识（如 ID）、状态可变化的业务对象，核心是“身份”而非属性。订单（Order）：有唯一订单 ID，状态会从“待支付”变为“已完成”。值对象（Value Object）无唯一标识、不可变（创建后属性不修改）的业务对象，核心是“属性组合的含义”。收货地址（Address）：由“省、市、街道、邮编”组成，无 ID；金额（Money）：由“数值 + 币种”组成，不可修改（如需改金额，需新建 Money 对象）。聚合（Aggregate）由“实体 + 值对象”组成的“业务单元”，确保单元内数据一致性，对外暴露唯一“聚合根”。订单聚合：聚合根是“订单（Entity）”，包含“订单项（Value Object，如商品 ID、数量）”、“收货地址（Value Object）”；外部只能通过“订单 ID"操作聚合内的对象，避免直接修改“订单项”导致数据不一致。聚合根（Aggregate Root）聚合的“入口”，是聚合内唯一允许被外部访问的实体，负责维护聚合内的业务规则。订单（Order）是聚合根，外部要修改订单项，必须通过“订单的修改订单项方法”（而非直接操作订单项），确保订单项数量不超过商品库存。领域服务（Domain Service）封装“跨实体/跨聚合”的业务逻辑，本身无状态，仅负责协调领域对象完成业务操作。订单支付服务（OrderPaymentService）：协调“订单（修改状态）”、“支付（创建支付记录）”、“库存（扣减库存）”三个聚合，完成“支付成功后更新订单状态”的逻辑。领域事件（Domain Event）记录领域中发生的“重要业务事件”，用于实现“跨上下文通信”或“异步业务流程”。订单支付成功事件（OrderPaidEvent）：订单支付完成后发布此事件，“物流上下文”监听事件后自动创建物流单，“积分上下文”监听事件后为用户增加积分。仓储（Repository）封装领域对象的“持久化逻辑”（如数据库 CRU…

DDD接口层介绍
type: item
date: 2026-07-07T08:28:39+00:00
description: DDD 接口层（表现层）全面介绍在 DDD（领域驱动设计，Domain-Driven Design）的分层架构中，接口层（Interface Layer） 又称 表现层（Presentation Layer），是系统与外部（用户、其他系统）交互的“入口和出口”。它处于分层架构的最外层，负责接收外部请求、传递给内层处理，并将处理结果反馈给外部。其核心价值是 隔离外部交互逻辑与内部业务逻辑，确保领域层（核心业务）不被外部交互方式（如 API、消息队列）的变更所影响。一、接口层的核心定位与职责接口层是 DDD 分层架构的“对外窗口”，不包含任何 核心业务逻辑（业务逻辑由领域层和应用层实现），仅聚焦“交互能力”。其核心职责可概括为以下三点：请求接收与解析 接收外部输入的请求（如用户通过 APP 提交的订单、第三方系统通过 API 推送的支付结果），并将请求格式（如 JSON、XML、消息体）解析为应用层可处理的“领域友好型”参数（如 OrderCreateCommand 命令对象、UserId 值对象）。示例：用户提交的订单 JSON 中包含“商品 ID 列表、收货地址、优惠券 ID"，接口层需将这些字段解析为应用层的 CreateOrderRequest 对象，并校验参数合法性（如商品 ID 非空、收货地址格式正确）。请求路由与转发 将解析后的请求，按业务场景路由到对应的 应用层服务（Application Service），由应用层协调领域层完成业务处理。关键：接口层不直接调用领域层对象（如实体、领域服务），必须通过应用层“中转”，确保业务逻辑的封装性。示例：“创建订单”接口接收请求后，需调用应用层的 OrderApplicationService.createOrder(CreateOrderRequest.html) 方法，而非直接创建 Order 实体。结果转换与反馈 接收应用层返回的处理结果（如订单 ID、业务状态），并将结果转换为外部可理解的格式（如 JSON、状态码、消息通知），反馈给请求方。示例：应用层返回 OrderDTO（包含订单 ID、创建时间、订单状态），接口层需将其转换为 JSON 格式，并附带 HTTP 状态码（如 200 表示成功、400 表示参数错误）返回给前端。二、接口层的常见实现形式接口层的实现形式取决于“外部交互场景”，不同场景对应不同的交互载体。常见形式可分为以下 4 类：实现形式适用场景技术示例（Java 生态）核心特点API 接口（同步）外部系统/前端与系统的实时交互（如查询订单、创建支付）RESTful API（Spring MVC/Spring WebFlux）、gRPC实时响应、同步通信，需处理超时、重试问题消息接口（异步）非实时交互（如支付结果通知、物流状态同步）消息队列（RabbitMQ/Kafka）、事件总线（Spring Event）异步解耦、削峰填谷，需处理消息幂等、重试、死信前端页面接口面向用户的 Web/APP 前端交互（如用户登录、商品列表）页面渲染（Thymeleaf/Vue）、AJAX 接口（Spring MVC）需适配前端视图，返回页面或前端所需的 JSON 数据批量接口（批处理）批量数据交互（如批量导入订单、批量查询物流）批量 API（分页查询、Excel 导入接口）、定时任务接收端处理大量数据，需考虑性能（如分页、异步批量处理）三、接口层的核心组件与设计原则1. 核心组件（以 API 接口为例）接口层的组件设计需遵循“轻量化、职责单一”原则，避免冗余逻辑。典型组件包括：（1）请求处理器（Controller/Handler）定位：接口层的“入口点”，直接接收外部请求。职责：绑定请求路径（如 /api/v1/orders）和 HTTP 方法（GET/POST）；接收请求参数（路径参数、请求体、Query 参数）；调用应用层服务，触发业务处理；返回处理结果（如 JSON、视图）。示例（Spring MVC）：@RestController @RequestMapping("/api/v1/orders".html) public class OrderController { // 依赖注入应用层服务（不依赖领域层） private final OrderApplicationService orderApplicationService; // 创建订单接口 @PostMapping public ResponseEntity<OrderResponse> createOrder(@RequestBody @Valid CreateOrderRequest request.html) { // 调用应用层服务处理业务 OrderDTO orderDTO = o…

DDD应用层和领域层的区别
type: item
date: 2026-07-07T08:28:03+00:00
description: 在 DDD（领域驱动设计，Domain-Driven Design）的分层架构中，应用层（Application Layer） 和 领域层（Domain Layer） 是核心层级。二者的定位、职责和关注点存在本质区别，但又必须协同工作以实现业务需求。以下从核心定位、职责、包含组件、设计原则及代码示例等方面，详细对比两者的区别。一、核心定位：“做什么”与“怎么做”领域层：聚焦 “业务本质”，回答“业务是什么”、“业务规则是什么”。它是系统的 业务内核，封装了领域的核心概念、业务规则和逻辑，是业务知识的软件化体现，原则上不依赖任何具体技术实现。应用层：聚焦 “业务流程”，回答“如何利用领域层的能力完成用户需求”。它是领域层的 “使用者和协调者”，不包含核心业务逻辑，仅负责组织和调度领域层的对象，完成跨领域的业务流程。二、核心职责：业务逻辑 vs 流程编排1. 领域层的核心职责领域层是业务逻辑的 核心载体，负责 实现所有核心业务规则，解决“业务本身的问题”。具体包括：封装领域概念：如“订单”、“商品”、“支付”，通过 实体（Entity） 和 值对象（Value Object） 表达业务对象；实现业务规则：如“订单金额 = 商品总价 + 运费 - 优惠券”、“订单状态只能从‘待支付’流转到‘已支付’或‘已取消’"；处理复杂计算：如“折扣计算”、“税费计算”；维护对象关系：如“订单包含多个订单项”、“用户拥有多个地址”；跨对象逻辑：通过 领域服务（Domain Service） 处理跨实体或跨值对象的领域逻辑（如“订单支付时需同时扣减库存和增加积分”）。一句话总结：领域层“知道业务该如何运作”，是系统的“业务大脑”。2. 应用层的核心职责应用层不包含核心业务逻辑，而是 协调领域层的能力完成用户的具体需求，解决“如何组织业务步骤”的问题。具体包括：接收请求：接收接口层传递的用户请求（如“创建订单”、“取消支付”）；调度对象：按业务流程调度领域层的对象（实体、领域服务）和基础设施层的技术服务（如仓储、缓存）；事务管理：管理业务流程的事务边界（如“创建订单时，需保证‘扣减库存’和‘保存订单’要么同时成功，要么同时失败”）；跨上下文通信：处理跨限界上下文（Bounded Context）的通信（如“订单支付成功后，通知物流上下文创建物流单”）；数据转换：将领域层的处理结果转换为应用层 DTO（数据传输对象），返回给接口层。一句话总结：应用层“知道如何调用业务能力完成任务”，是系统的“业务流程指挥官”。三、包含的核心组件：业务对象 vs 流程服务1. 领域层的核心组件领域层的组件直接映射业务概念，是“业务知识的载体”：实体（Entity）：有唯一标识、状态可变的业务对象（如 Order、Product），包含自身的业务行为（如 Order.pay() 处理支付逻辑）；值对象（Value Object）：无唯一标识、不可变的业务对象（如 Money、Address），用于描述实体的属性；聚合（Aggregate）：由实体和值对象组成的业务单元（如 OrderAggregate 包含 Order 实体和 OrderItem 值对象），确保数据一致性；聚合根（Aggregate Root）：聚合的入口点（如 Order 是订单聚合的根），控制外部对聚合内对象的访问；领域服务（Domain Service）：无状态的服务，封装跨实体或跨聚合的领域逻辑（如 OrderPaymentService 协调订单和库存的交互）；领域事件（Domain Event）：记录领域内发生的重要事件（如 OrderPaidEvent），用于领域内或跨上下文的通知；仓储接口（Repository Interface）：定义领域对象的持久化抽象（如 OrderRepository），不包含具体实现。2. 应用层的核心组件应用层的组件聚焦流程编排，是“业务能力的组织者”：应用服务（Application Service）：核心组件，每个服务对应一个业务用例（如 OrderApplicationService 包含 createOrder()、cancelOrder() 方法），负责调用领域层和基础设施层完成流程；命令/查询对象（Command/Query）：封装应用层的输入参数（如 CreateOrderCommand 包含创建订单所需的用户 ID、商品列表等），与接口层的 Request 对象对应；DTO（Data Transfer Object）：封装应用层的输出结果（如 OrderDTO 包含订单 ID、状态、金额等），用于向接口层传递数据，与领域对象解耦；应用事件（Application Event）：记录应用层的流程事件（如 OrderCreatedEvent），用于…

DDD中的Assembler（装配器）介绍
type: item
date: 2026-07-07T08:25:57+00:00
description: DDD 中的 Assembler（装配器）：对象转换的桥梁在领域驱动设计（DDD）中，Assembler（装配器） 是负责不同层级对象之间转换的关键组件。其核心职责是实现领域对象（如实体、值对象）与数据传输对象（DTO）、数据库实体（DO）等不同类型对象之间的属性映射与转换，同时在转换过程中保持各层架构之间的解耦。Assembler 的核心价值在 DDD 分层架构中，不同层次所使用的对象模型承担着不同的职责：领域层：使用领域对象（实体、值对象），封装核心业务逻辑与规则。应用层与接口层：使用DTO（Data Transfer Object，数据传输对象），专注于数据传递。基础设施层：使用数据库实体（DO），专注于数据持久化。Assembler 的核心价值主要体现在以下三个方面：隔离模型：隔离不同层的对象模型，避免层级间的紧耦合。集中管控：集中管理对象转换逻辑，提高代码的复用性与可维护性。隐藏细节：隐藏对象转换的复杂细节，使各层能够聚焦于自身的核心职责。Assembler 的主要职责领域对象与 DTO 之间的转换将领域对象（实体/值对象）转换为 DTO，供应用层和接口层使用。将 DTO 转换为领域对象或命令对象（Command），供领域层处理。领域对象与数据库实体（DO）之间的转换将领域对象转换为数据库实体，用于数据持久化操作。将数据库实体转换为领域对象，用于后续业务处理。处理复杂对象关系处理聚合对象内部的嵌套转换。处理集合类型对象的批量转换。处理不同命名规范和数据类型的映射差异。Assembler 的实现方式1. 手动实现的 Assembler最为常见的方式是创建专门的 Assembler 类，手动编写对象转换逻辑。这种方式控制力最强，适合转换逻辑复杂或需要特殊处理的场景。// 订单领域对象 public class Order { private OrderId id; private UserId userId; private Money totalAmount; private List<OrderItem> items; private OrderStatus status; // 业务方法... } // 订单 DTO public class OrderDTO { private String orderId; private String userId; private BigDecimal totalAmount; private String currency; private List<OrderItemDTO> items; private String status; // getter 和 setter... } // 订单 Assembler public class OrderAssembler { // 领域对象转 DTO public OrderDTO toDTO(Order order.html) { OrderDTO dto = new OrderDTO(); dto.setOrderId(order.getId(.html).getValue()); dto.setUserId(order.getUserId(.html).getValue()); dto.setTotalAmount(order.getTotalAmount(.html).getAmount()); dto.setCurrency(order.getTotalAmount(.html).getCurrency().getCode()); dto.setStatus(order.getStatus(.html).getName()); // 处理集合转换 dto.setItems(order.getItems(.html).stream() .map(this::toOrderItemDTO.html) .collect(Collectors.toList(.html))); return dto; } // DTO 转领域对象 public Order toDomain(OrderDTO dto.html) { Order order = new Order( new OrderId(dto.getOrderId(.html)), new UserId(dto.getUserId(.html)), new Money(dto.getTotalAmount(.html), Currency.of(dto.getCurrency(.html))), OrderStatus.fromName(dto.getStatus(.html)) ); // 添加订单项 if (dto.getItems(.html) != null) …

DDD中Infrastructure（基础设施层）介绍
type: item
date: 2026-07-07T08:24:54+00:00
description: DDD 中 Infrastructure（基础设施层）的核心作用与价值在 DDD（领域驱动设计，Domain-Driven Design）的分层架构中，Infrastructure（基础设施层） 是整个系统的“技术支撑底座”。它处于分层架构的最底层，为领域层（核心业务）、应用层（业务编排）和接口层（对外交互）提供“非业务相关的技术能力”。其核心价值在于隔离技术实现与业务逻辑，确保领域层（系统的业务内核）不被技术框架、存储方案或第三方服务的变更所影响。一、基础设施层的核心定位：“服务者”与“实现者”DDD 的分层架构遵循“业务内聚、技术外移”的原则——领域层聚焦"What（业务要做什么）"，而基础设施层聚焦"How（技术上如何实现）"。具体定位可概括为两点：技术能力的提供者：为上层（领域层、应用层）提供通用技术服务，如数据持久化、缓存、日志、消息通信、第三方接口集成等；抽象接口的实现者：领域层会定义“业务需要的抽象能力”（如仓储接口 OrderRepository、事件发布接口 DomainEventPublisher），而基础设施层负责将这些抽象接口落地为具体的技术实现（如基于 MySQL 的 OrderRepositoryImpl、基于 Kafka 的 KafkaDomainEventPublisher）。二、基础设施层的核心作用（四大核心能力）基础设施层的作用围绕“支撑上层业务”展开，具体可拆解为四大核心能力。每类能力都直接服务于上层的业务需求，且不侵入业务逻辑本身。1. 实现领域层的抽象依赖：让业务逻辑“不绑定技术”领域层为了保持“纯业务属性”，会通过接口定义业务所需的技术能力（如“保存订单”“查询商品库存”），但不关心这些能力的技术实现（是用 MySQL 还是 MongoDB，是查本地库还是调用第三方 API）。基础设施层的核心职责之一，就是实现这些抽象接口，让领域层的业务逻辑能“无感知”地使用技术能力。典型场景：实现领域层的仓储接口（Repository）仓储（Repository）是领域层定义的“领域对象持久化抽象”，用于描述“如何保存/查询领域对象”（如 OrderRepository 定义 save(Order order.html) 和 getById(String orderId.html) 方法），但不包含任何数据库操作逻辑。基础设施层则通过具体的技术框架（如 MyBatis、JPA、Spring Data）实现这些接口，完成数据与数据库的交互。示例：订单仓储的抽象与实现领域层（仅定义抽象接口，无技术依赖）：// 领域层：订单仓储接口（抽象定义“保存订单”的业务需求） public interface OrderRepository { // 保存订单领域对象（参数是领域层的 Order 实体，纯业务对象） Order save(Order order.html); // 根据订单 ID 查询订单领域对象 Order getById(String orderId.html); }基础设施层（实现抽象接口，绑定具体技术）：// 基础设施层：基于 MySQL 的订单仓储实现（技术落地） @Repository // 技术框架注解（Spring），与业务无关 public class OrderRepositoryImpl implements OrderRepository { // 依赖数据访问框架（MyBatis 的 Mapper 接口，技术组件） private final OrderMapper orderMapper; // 依赖值对象转换器（将领域对象的属性转换为数据库表字段） private final OrderDataConverter converter; @Override public Order save(Order order.html) { // 1. 领域对象（Order）转换为数据库实体（OrderDO）——技术层面的属性映射 OrderDO orderDO = converter.toDO(order.html); // 2. 调用 MyBatis Mapper 操作数据库（具体技术实现） if (StringUtils.isEmpty(orderDO.getId(.html))) { orderMapper.insert(orderDO.html); // 新增订单 } else { orderMapper.updateById(orderDO.html); // 更新订单 } // 3. 数据库实体转换回领域对象，返回给领域层（业务层无需关心数据库字段） return converter.toDomain(orderDO.html); } @Override publi…