← 返回首页
🏗️

分层架构详解

📂 architecture ⏱ 3 min 537 words

分层架构详解

分层架构的基本概念

分层架构是一种将软件系统划分为多个水平层的架构模式,每层只与相邻层交互。这种模式通过关注点分离来降低系统复杂性,提高可维护性和可测试性。

经典分层模型

四层架构

最常见的分层架构包含四个层次:

┌─────────────────────────┐
│     表示层 (UI)          │  用户界面、用户交互
├─────────────────────────┤
│   业务逻辑层 (BLL)       │  业务规则、流程处理
├─────────────────────────┤
│  数据访问层 (DAL)        │  数据持久化、ORM
├─────────────────────────┤
│     数据库层 (DB)        │  数据存储
└─────────────────────────┘

五层架构

在某些场景下,会在业务逻辑层和数据访问层之间增加一个服务层:

┌─────────────────────────┐
│     表示层 (UI)          │
├─────────────────────────┤
│   业务逻辑层 (BLL)       │
├─────────────────────────┤
│     服务层 (Service)     │  领域服务、用例编排
├─────────────────────────┤
│  数据访问层 (DAL)        │
├─────────────────────────┤
│     数据库层 (DB)        │
└─────────────────────────┘

各层职责详解

表示层

表示层负责处理用户界面和用户交互,不包含任何业务逻辑。

// 表示层 - REST Controller
@RestController
@RequestMapping("/api/v1/orders")
public class OrderController {
    
    private final OrderFacade orderFacade;
    
    public OrderController(OrderFacade orderFacade) {
        this.orderFacade = orderFacade;
    }
    
    @GetMapping("/{id}")
    public ResponseEntity<OrderDto> getOrder(@PathVariable Long id) {
        OrderDto order = orderFacade.getOrder(id);
        return ResponseEntity.ok(order);
    }
    
    @PostMapping
    public ResponseEntity<OrderDto> createOrder(@RequestBody CreateOrderRequest request) {
        OrderDto order = orderFacade.createOrder(request);
        return ResponseEntity.status(HttpStatus.CREATED).body(order);
    }
    
    @PutMapping("/{id}/status")
    public ResponseEntity<Void> updateOrderStatus(
            @PathVariable Long id,
            @RequestBody UpdateStatusRequest request) {
        orderFacade.updateOrderStatus(id, request.getStatus());
        return ResponseEntity.ok().build();
    }
}

业务逻辑层

业务逻辑层包含核心业务规则和流程,是系统最重要的层次。

// 业务逻辑层 - 领域服务
@Service
@Transactional
public class OrderDomainService {
    
    private final OrderRepository orderRepository;
    private final InventoryService inventoryService;
    private final PricingService pricingService;
    
    public OrderDomainService(
            OrderRepository orderRepository,
            InventoryService inventoryService,
            PricingService pricingService) {
        this.orderRepository = orderRepository;
        this.inventoryService = inventoryService;
        this.pricingService = pricingService;
    }
    
    public Order createOrder(CreateOrderCommand command) {
        // 业务规则验证
        validateOrder(command);
        
        // 创建订单聚合根
        Order order = OrderFactory.create(command);
        
        // 应用业务规则
        order.applyPricing(pricingService.calculatePrice(order));
        order.reserveInventory(inventoryService);
        
        // 持久化
        return orderRepository.save(order);
    }
    
    private void validateOrder(CreateOrderCommand command) {
        if (command.getItems() == null || command.getItems().isEmpty()) {
            throw new InvalidOrderException("Order must contain at least one item");
        }
        
        for (OrderItem item : command.getItems()) {
            if (item.getQuantity() <= 0) {
                throw new InvalidOrderException("Invalid quantity for item: " + item.getProductId());
            }
        }
    }
}

数据访问层

数据访问层负责与数据存储交互,隐藏数据持久化的细节。

// 数据访问层 - Repository
@Repository
public class JpaOrderRepository implements OrderRepository {
    
    private final OrderJpaRepository jpaRepository;
    private final OrderMapper mapper;
    
    public JpaOrderRepository(OrderJpaRepository jpaRepository, OrderMapper mapper) {
        this.jpaRepository = jpaRepository;
        this.mapper = mapper;
    }
    
    @Override
    public Order save(Order order) {
        OrderJpaEntity entity = mapper.toJpaEntity(order);
        OrderJpaEntity savedEntity = jpaRepository.save(entity);
        return mapper.toDomainEntity(savedEntity);
    }
    
    @Override
    public Optional<Order> findById(Long id) {
        return jpaRepository.findById(id)
                .map(mapper::toDomainEntity);
    }
    
    @Override
    public List<Order> findByCustomerId(Long customerId) {
        return jpaRepository.findByCustomerId(customerId)
                .stream()
                .map(mapper::toDomainEntity)
                .collect(Collectors.toList());
    }
}

// JPA实体
@Entity
@Table(name = "orders")
public class OrderJpaEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @Column(name = "customer_id")
    private Long customerId;
    
    @Enumerated(EnumType.STRING)
    private OrderStatus status;
    
    @Column(name = "total_amount")
    private BigDecimal totalAmount;
    
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "order_id")
    private List<OrderItemJpaEntity> items;
    
    // getters and setters
}

层间通信机制

依赖方向

分层架构的一个关键原则是依赖方向:上层依赖下层,下层不知道上层的存在。

表示层 → 业务逻辑层 → 数据访问层 → 数据库层

DTO(数据传输对象)

DTO用于在层间传输数据,避免直接暴露领域模型或数据库实体。

// DTO定义
public class OrderDto {
    private Long id;
    private Long customerId;
    private String status;
    private BigDecimal totalAmount;
    private List<OrderItemDto> items;
    private LocalDateTime createdAt;
}

public class OrderItemDto {
    private Long productId;
    private String productName;
    private Integer quantity;
    private BigDecimal unitPrice;
    private BigDecimal totalPrice;
}

// 请求DTO
public class CreateOrderRequest {
    private Long customerId;
    private List<CreateOrderItemRequest> items;
}

// 响应DTO
public class OrderResponse {
    private OrderDto order;
    private String message;
}

Facade模式

Facade模式为复杂子系统提供一个简单的接口,简化表示层的调用。

// Facade实现
@Service
public class OrderFacade {
    
    private final OrderDomainService orderDomainService;
    private final OrderQueryService orderQueryService;
    private final OrderMapper orderMapper;
    
    public OrderDto getOrder(Long id) {
        Order order = orderQueryService.findById(id);
        return orderMapper.toDto(order);
    }
    
    public OrderDto createOrder(CreateOrderRequest request) {
        CreateOrderCommand command = orderMapper.toCommand(request);
        Order order = orderDomainService.createOrder(command);
        return orderMapper.toDto(order);
    }
    
    public void updateOrderStatus(Long id, String status) {
        OrderStatus orderStatus = OrderStatus.valueOf(status);
        orderDomainService.updateOrderStatus(id, orderStatus);
    }
}

分层架构的优缺点

优点

缺点

最佳实践

  1. 严格遵循依赖方向:上层依赖下层,禁止反向依赖
  2. 使用DTO传输数据:避免直接暴露领域模型
  3. 保持层的独立性:每层应该可以独立测试和替换
  4. 合理划分层次:根据项目复杂度决定层次数量
  5. 文档化层间接口:清晰定义每层的职责和接口