DDD的分层架构是怎么样的?

领域驱动设计(DDD)的分层架构旨在通过关注点分离职责明确来组织代码,使领域模型成为系统的核心,并隔离技术复杂性。以下是典型的分层架构及其职责,结合Java代码示例说明:


DDD分层架构(经典四层)

1. 用户接口层(User Interface Layer / Presentation Layer)

  • 职责

    • 处理用户输入(HTTP请求、命令行、消息队列等)。
    • 返回响应(JSON、HTML等)。
    • 不包含业务逻辑,仅负责输入/输出转换。
  • Java实现

    java 复制代码
    // 示例:Spring MVC的Controller
    @RestController
    @RequestMapping("/orders")
    public class OrderController {
        @Autowired
        private OrderApplicationService orderAppService;
    
        @PostMapping
        public ResponseEntity<Void> createOrder(@RequestBody CreateOrderRequest request) {
            // 1. 转换DTO为领域对象
            CreateOrderCommand command = new CreateOrderCommand(request.getItems());
            // 2. 调用应用服务
            orderAppService.createOrder(command);
            return ResponseEntity.ok().build();
        }
    }

2. 应用层(Application Layer)

  • 职责

    • 协调领域对象完成用例(如事务管理、权限校验)。
    • 不包含核心业务逻辑,仅定义用例流程。
    • 调用领域层的聚合根和领域服务。
  • Java实现

    java 复制代码
    @Service
    public class OrderApplicationService {
        @Autowired
        private OrderRepository orderRepository;
        @Autowired
        private EventPublisher eventPublisher;
    
        @Transactional
        public void createOrder(CreateOrderCommand command) {
            // 1. 创建聚合根
            Order order = new Order(UUID.randomUUID().toString());
            // 2. 调用领域对象方法
            command.getItems().forEach(order::addItem);
            // 3. 持久化
            orderRepository.save(order);
            // 4. 发布领域事件(跨聚合操作)
            eventPublisher.publish(new OrderCreatedEvent(order.getId()));
        }
    }

3. 领域层(Domain Layer)

  • 职责

    • 系统的核心,包含领域模型(实体、值对象、聚合根、领域服务)。
    • 封装业务规则和不变条件。
    • 不依赖任何其他层(完全独立于技术和框架)。
  • Java实现

    java 复制代码
    // 聚合根
    public class Order {
        private String orderId;
        private List<OrderItem> items;
        private OrderStatus status;
    
        public void addItem(OrderItem item) {
            if (status != OrderStatus.DRAFT) {
                throw new IllegalStateException("Cannot modify a confirmed order");
            }
            items.add(item);
        }
    
        public void confirm() {
            if (items.isEmpty()) throw new IllegalStateException("Empty order");
            this.status = OrderStatus.CONFIRMED;
        }
    }
    
    // 领域服务(处理跨聚合逻辑)
    public class OrderValidationService {
        public void validateOrder(Order order) {
            // 复杂的业务规则校验
        }
    }

4. 基础设施层(Infrastructure Layer)

  • 职责

    • 实现技术细节:数据库访问、消息队列、缓存、外部API调用等。
    • 实现领域层的接口(如仓储接口)。
  • Java实现

    java 复制代码
    // 实现领域层的仓储接口(JPA)
    @Repository
    public class JpaOrderRepository implements OrderRepository {
        @Autowired
        private OrderJpaRepository jpaRepository; // Spring Data JPA接口
    
        @Override
        public Order findById(String orderId) {
            OrderJpaEntity entity = jpaRepository.findById(orderId).orElseThrow();
            return convertToDomain(entity);
        }
    
        // 省略转换逻辑
    }
    
    // 消息队列实现(如Kafka)
    @Component
    public class KafkaEventPublisher implements EventPublisher {
        @Override
        public void publish(DomainEvent event) {
            kafkaTemplate.send("order-events", event);
        }
    }

分层依赖关系

  • 单向依赖
    用户接口层 → 应用层 → 领域层
    基础设施层 → 领域层

    (通过依赖倒置原则,领域层定义接口,基础设施层实现接口)

  • 关键原则

    • 领域层完全独立:不依赖Spring、JPA等技术框架。
    • 避免基础设施层侵入领域模型:领域对象不包含JPA注解或框架依赖。

代码结构示例(Maven/Gradle项目)

plaintext 复制代码
src/main/java
├── com.example
│   ├── application            // 应用层
│   │   ├── OrderApplicationService.java
│   │   └── dto               // DTO定义
│   ├── domain                // 领域层
│   │   ├── model             // 聚合根、实体、值对象
│   │   ├── service           // 领域服务
│   │   ├── event             // 领域事件
│   │   └── repository        // 仓储接口(领域层定义)
│   ├── infrastructure        // 基础设施层
│   │   ├── persistence       // 数据库实现(JPA)
│   │   ├── messaging         // 消息队列实现(Kafka)
│   │   └── rest              // 外部API调用
│   └── interfaces            // 用户接口层
│       ├── web               // HTTP接口(Controller)
│       └── cli               // 命令行接口

各层交互流程(以创建订单为例)

  1. 用户接口层 接收HTTP请求,将JSON转换为CreateOrderCommand
  2. 应用层 调用OrderApplicationService
    • 创建Order聚合根。
    • 调用order.addItem()添加商品项。
    • 调用仓储保存订单。
    • 发布OrderCreatedEvent
  3. 领域层 执行核心业务逻辑:
    • Order聚合根校验状态和商品数量。
  4. 基础设施层
    • JpaOrderRepositoryOrder持久化到数据库。
    • KafkaEventPublisher将事件发送到消息队列。

分层架构的优势

  1. 高内聚低耦合:领域层与技术实现解耦。
  2. 可测试性:领域层可脱离框架单独测试。
  3. 适应变化:技术栈替换(如数据库从MySQL切到MongoDB)只需修改基础设施层。
  4. 清晰的职责划分:避免代码混杂(如业务逻辑侵入Controller)。

常见误区与解决方案

误区 解决方案
业务逻辑泄露到应用层或Controller 将逻辑内聚到领域对象(充血模型)。
领域层依赖Spring/JPA 通过依赖倒置,领域层仅定义接口。
基础设施层直接依赖领域层具体类 通过接口隔离,基础设施层实现领域层接口。

总结

DDD的分层架构通过领域层为核心,隔离技术与业务逻辑,确保软件的可维护性和扩展性。作为Java工程师,应重点关注:

  1. 领域层的纯粹性:避免技术框架污染领域模型。
  2. 依赖方向控制:通过接口和依赖倒置解耦各层。
  3. 代码结构清晰:模块化组织限界上下文(如每个上下文独立为子模块)。
相关推荐
自珍JAVA10 分钟前
Gobrs-Async 框架
后端
xdscode15 分钟前
Spring 依赖注入方式全景解析
java·后端·spring
青柠代码录23 分钟前
【Spring】@Component VS @Configuration
后端
喵个咪1 小时前
go-wind-cms 微服务架构设计:为什么基于 Kratos?
后端·微服务·cms
神奇小汤圆1 小时前
百度面试官:Redis 内存满了怎么办?你有想过吗?
后端
喵个咪1 小时前
Headless 架构优势:内容与展示解耦,一套 API 打通全端生态
前端·后端·cms
开心就好20251 小时前
HTTPS超文本传输安全协议全面解析与工作原理
后端·ios
小江的记录本1 小时前
【JEECG Boot】 JEECG Boot——数据字典管理 系统性知识体系全解析
java·前端·spring boot·后端·spring·spring cloud·mybatis
神奇小汤圆1 小时前
Spring Batch实战
后端
喵个咪1 小时前
传统 CMS 太笨重?试试 Headless 架构的 GoWind,轻量又强大
前端·后端·cms