DDD领域驱动设计在微服务架构中的最佳实践:从领域建模到代码实现的完整指南

RedDust
RedDust 2026-01-13T04:09:27+08:00
0 0 0

引言

在现代软件开发中,随着业务复杂度的不断增加和系统规模的持续扩大,传统的软件架构模式已经难以满足企业级应用的需求。领域驱动设计(Domain-Driven Design, DDD)作为一种重要的软件设计方法论,为解决复杂业务场景下的软件架构问题提供了有力支撑。特别是在微服务架构日益普及的今天,如何将DDD理念与微服务实践有机结合,成为了架构师和开发团队面临的重要课题。

本文将深入探讨DDD在微服务架构中的最佳实践,从核心概念入手,通过详细的领域建模过程,到限界上下文的划分,再到聚合根的设计,最终展示如何将理论转化为可维护的代码实现。通过实际业务案例的演示,帮助读者理解如何在真实的项目中应用这些技术。

什么是领域驱动设计(DDD)

DDD的核心理念

领域驱动设计是由Eric Evans在其2004年出版的《领域驱动设计:软件核心复杂性应对之道》一书中首次提出的。DDD的核心理念是将软件开发的重点从技术实现转向业务领域的深入理解,通过建立精确的领域模型来指导软件架构和代码设计。

DDD强调:

  • 领域驱动:以业务领域为核心,围绕业务需求进行软件设计
  • 统一语言:在团队内部建立业务术语和代码术语的一致性
  • 模型驱动:通过领域模型指导软件结构设计
  • 持续演进:随着业务发展不断优化和完善领域模型

DDD的核心概念

在DDD中,有几个核心概念需要理解:

  1. 领域(Domain):业务问题所在的范围或领域,如电商、银行、医疗等
  2. 子域(Subdomain):领域中的一个具体方面,如电商领域的订单管理、库存管理
  3. 限界上下文(Bounded Context):明确的边界,定义了模型在特定上下文中如何被理解和使用
  4. 聚合根(Aggregate Root):聚合的核心对象,负责维护聚合内部的一致性
  5. 实体(Entity):具有唯一标识的对象,其生命周期贯穿整个业务过程
  6. 值对象(Value Object):没有唯一标识的对象,通过属性来区分

DDD在微服务架构中的价值

微服务与DDD的天然契合

微服务架构和DDD在设计理念上有着天然的契合性。微服务强调将大型应用拆分为小的、独立的服务,每个服务都有明确的业务边界;而DDD同样强调通过领域划分来构建清晰的业务模型。这种相似性使得DDD成为微服务架构设计的理想指导原则。

解决微服务设计中的常见问题

在微服务设计过程中,团队常常面临以下挑战:

  1. 服务拆分困难:如何确定服务的边界
  2. 数据一致性问题:分布式环境下的事务处理
  3. 团队协作障碍:不同团队间的技术术语不统一
  4. 系统维护成本高:缺乏清晰的业务模型指导

DDD通过其核心概念和实践方法,为解决这些问题提供了系统的解决方案。

领域建模实践

业务分析与领域识别

领域建模的第一步是深入理解业务。以一个电商系统为例,我们需要从以下角度进行分析:

// 业务场景分析示例
public class BusinessAnalysis {
    // 核心业务流程
    public void analyzeBusinessProcesses() {
        // 1. 用户注册与登录
        // 2. 商品浏览与搜索
        // 3. 购物车管理
        // 4. 订单处理
        // 5. 支付结算
        // 6. 物流配送
        // 7. 售后服务
    }
    
    // 业务实体识别
    public void identifyBusinessEntities() {
        // User(用户)
        // Product(商品)
        // CartItem(购物车项)
        // Order(订单)
        // Payment(支付)
        // Shipping(配送)
    }
}

核心领域与支撑领域

在电商系统中,我们可以将领域划分为:

// 领域划分示例
public class DomainClassification {
    
    // 核心领域(Core Domain)
    // 业务价值最高,最复杂的核心业务逻辑
    public static final String ORDER_MANAGEMENT = "订单管理";
    public static final String PAYMENT_PROCESSING = "支付处理";
    
    // 支撑领域(Supporting Domain)
    // 辅助核心领域,提供基础服务支持
    public static final String USER_MANAGEMENT = "用户管理";
    public static final String INVENTORY_MANAGEMENT = "库存管理";
    
    // 通用领域(Generic Domain)
    // 可以复用的技术组件
    public static final String EMAIL_SERVICE = "邮件服务";
    public static final String LOGGING_SERVICE = "日志服务";
}

统一语言的建立

统一语言是DDD的重要基础。在电商系统中,我们需要建立一套一致的术语体系:

// 统一语言示例
public class UnifiedLanguage {
    
    // 业务术语与代码术语映射
    public static final String USER = "用户";
    public static final String CUSTOMER = "客户";
    public static final String PRODUCT = "商品";
    public static final String ORDER = "订单";
    public static final String PAYMENT = "支付";
    public static final String TRANSACTION = "交易";
    
    // 业务规则表达
    public static final String ORDER_STATUS_CREATED = "已创建";
    public static final String ORDER_STATUS_PAID = "已支付";
    public static final String ORDER_STATUS_SHIPPED = "已发货";
    public static final String ORDER_STATUS_DELIVERED = "已送达";
    public static final String ORDER_STATUS_CANCELLED = "已取消";
}

限界上下文划分

限界上下文的概念与重要性

限界上下文是DDD中的核心概念,它定义了模型在特定范围内的含义和使用方式。每个限界上下文都有自己的领域模型、术语体系和业务规则。

// 限界上下文划分示例
public class BoundedContext {
    
    // 用户管理上下文
    public static class UserManagementContext {
        // 业务范围:用户注册、登录、权限管理
        // 核心实体:User, Role, Permission
        // 统一语言:用户、角色、权限
        
        public void handleUserRegistration() {
            // 用户注册逻辑
        }
        
        public void handleUserLogin() {
            // 用户登录逻辑
        }
    }
    
    // 订单管理上下文
    public static class OrderManagementContext {
        // 业务范围:订单创建、支付、发货
        // 核心实体:Order, OrderItem, Payment
        // 统一语言:订单、订单项、支付
        
        public void handleOrderCreation() {
            // 订单创建逻辑
        }
        
        public void handlePaymentProcessing() {
            // 支付处理逻辑
        }
    }
    
    // 库存管理上下文
    public static class InventoryManagementContext {
        // 业务范围:库存查询、库存扣减
        // 核心实体:Product, Inventory, Stock
        // 统一语言:商品、库存、库存量
        
        public void handleStockReservation() {
            // 库存预留逻辑
        }
        
        public void handleStockUpdate() {
            // 库存更新逻辑
        }
    }
}

上下文映射关系

不同的限界上下文之间需要建立清晰的映射关系:

// 上下文间的关系定义
public class ContextMapping {
    
    // 依赖关系
    public enum DependencyType {
        CUSTOMER_SERVICE_DEPENDS_ON_ORDER_SERVICE,  // 订单服务依赖用户服务
        ORDER_SERVICE_DEPENDS_ON_INVENTORY_SERVICE, // 订单服务依赖库存服务
        PAYMENT_SERVICE_DEPENDS_ON_ORDER_SERVICE    // 支付服务依赖订单服务
    }
    
    // 上下文间通信策略
    public enum CommunicationStrategy {
        DIRECT_CALL,      // 直接调用
        EVENT_DRIVEN,     // 事件驱动
        API_GATEWAY,      // API网关
        MESSAGE_QUEUE     // 消息队列
    }
}

聚合根设计

聚合根的核心概念

聚合根是DDD中用于维护数据一致性的核心概念。它是一个实体,负责确保其内部所有对象的一致性。

// 聚合根设计示例
public class Order {
    // 聚合根ID
    private final String orderId;
    
    // 聚合根属性
    private String customerName;
    private String customerEmail;
    private LocalDateTime orderDate;
    private OrderStatus status;
    
    // 聚合内部的实体和值对象
    private List<OrderItem> items;
    private Address shippingAddress;
    private Payment payment;
    
    // 构造函数
    public Order(String orderId, String customerName, String customerEmail) {
        this.orderId = orderId;
        this.customerName = customerName;
        this.customerEmail = customerEmail;
        this.orderDate = LocalDateTime.now();
        this.status = OrderStatus.CREATED;
        this.items = new ArrayList<>();
        this.payment = null;
    }
    
    // 聚合根方法 - 保证一致性
    public void addItem(OrderItem item) {
        if (status != OrderStatus.CREATED) {
            throw new IllegalStateException("只有在创建状态才能添加商品");
        }
        items.add(item);
    }
    
    public void confirmOrder() {
        if (items.isEmpty()) {
            throw new IllegalStateException("订单必须包含至少一个商品");
        }
        this.status = OrderStatus.CONFIRMED;
    }
    
    public void processPayment(Payment payment) {
        if (status != OrderStatus.CONFIRMED) {
            throw new IllegalStateException("只有确认状态的订单才能处理支付");
        }
        this.payment = payment;
        this.status = OrderStatus.PAID;
    }
    
    // Getter方法
    public String getOrderId() { return orderId; }
    public OrderStatus getStatus() { return status; }
    public List<OrderItem> getItems() { return new ArrayList<>(items); }
}

聚合根的设计原则

  1. 一致性边界:聚合根必须确保其内部所有对象的一致性
  2. 事务边界:每个聚合根的修改应该在单个事务中完成
  3. 稳定性:聚合根应该是相对稳定的,避免频繁变更
// 聚合根设计原则示例
public class AggregateRootPrinciples {
    
    // 原则1:确保内部一致性
    public static class ConsistentAggregate {
        private List<OrderItem> items;
        private BigDecimal totalAmount;
        
        public void addItem(OrderItem item) {
            items.add(item);
            // 自动计算总价,保证一致性
            calculateTotal();
        }
        
        private void calculateTotal() {
            this.totalAmount = items.stream()
                .map(OrderItem::getPrice)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        }
    }
    
    // 原则2:事务边界控制
    public static class TransactionBoundary {
        // 聚合根的修改必须在单个事务中完成
        public void updateOrderStatus(String orderId, OrderStatus newStatus) {
            // 通过聚合根来保证一致性
            Order order = orderRepository.findById(orderId);
            if (order != null) {
                // 在同一事务中更新订单状态
                order.setStatus(newStatus);
                orderRepository.save(order);
            }
        }
    }
}

实际业务案例:电商系统微服务架构设计

系统需求分析

让我们通过一个完整的电商系统来演示DDD在微服务架构中的应用。该系统需要支持用户管理、商品管理、订单处理、支付结算、库存管理等核心功能。

// 电商系统领域模型
public class ECommerceDomainModel {
    
    // 用户领域
    public static class UserDomain {
        private String userId;
        private String username;
        private String email;
        private String password;
        private List<Role> roles;
        
        // 用户操作
        public void register() { /* 注册逻辑 */ }
        public void login() { /* 登录逻辑 */ }
        public void updateProfile(UserProfile profile) { /* 更新资料 */ }
    }
    
    // 商品领域
    public static class ProductDomain {
        private String productId;
        private String name;
        private String description;
        private BigDecimal price;
        private Category category;
        private List<Attribute> attributes;
        
        // 商品操作
        public void updatePrice(BigDecimal newPrice) { /* 更新价格 */ }
        public void updateStock(int quantity) { /* 更新库存 */ }
    }
    
    // 订单领域
    public static class OrderDomain {
        private String orderId;
        private String userId;
        private List<OrderItem> items;
        private BigDecimal totalAmount;
        private OrderStatus status;
        
        // 订单操作
        public void createOrder() { /* 创建订单 */ }
        public void cancelOrder() { /* 取消订单 */ }
        public void processPayment() { /* 处理支付 */ }
    }
}

微服务架构设计

基于DDD分析,我们将电商系统划分为以下微服务:

// 微服务架构设计
public class MicroserviceArchitecture {
    
    // 1. 用户服务(UserService)
    public static class UserService {
        // 职责:用户注册、登录、权限管理
        // 限界上下文:User Management Context
        
        public User createUser(CreateUserRequest request) {
            // 用户创建逻辑
            return new User();
        }
        
        public boolean authenticate(String username, String password) {
            // 用户认证逻辑
            return true;
        }
    }
    
    // 2. 商品服务(ProductService)
    public static class ProductService {
        // 职责:商品管理、分类管理、属性管理
        // 限界上下文:Product Management Context
        
        public Product createProduct(CreateProductRequest request) {
            // 商品创建逻辑
            return new Product();
        }
        
        public List<Product> searchProducts(SearchCriteria criteria) {
            // 商品搜索逻辑
            return new ArrayList<>();
        }
    }
    
    // 3. 订单服务(OrderService)
    public static class OrderService {
        // 职责:订单创建、状态管理、支付处理
        // 限界上下文:Order Management Context
        
        public Order createOrder(CreateOrderRequest request) {
            // 订单创建逻辑
            return new Order();
        }
        
        public void updateOrderStatus(String orderId, OrderStatus status) {
            // 订单状态更新逻辑
        }
    }
    
    // 4. 库存服务(InventoryService)
    public static class InventoryService {
        // 职责:库存查询、库存扣减、库存预警
        // 限界上下文:Inventory Management Context
        
        public boolean reserveStock(String productId, int quantity) {
            // 库存预留逻辑
            return true;
        }
        
        public void updateStock(String productId, int newQuantity) {
            // 库存更新逻辑
        }
    }
}

聚合根实现示例

// 订单聚合根实现
public class OrderAggregate {
    // 聚合根ID
    private final String orderId;
    
    // 聚合根属性
    private String userId;
    private LocalDateTime orderDate;
    private OrderStatus status;
    private BigDecimal totalAmount;
    
    // 聚合内部的实体和值对象
    private List<OrderItem> items;
    private Address shippingAddress;
    private Payment payment;
    
    // 构造函数
    public OrderAggregate(String orderId, String userId) {
        this.orderId = orderId;
        this.userId = userId;
        this.orderDate = LocalDateTime.now();
        this.status = OrderStatus.CREATED;
        this.items = new ArrayList<>();
        this.totalAmount = BigDecimal.ZERO;
    }
    
    // 聚合根核心业务方法
    public void addItem(OrderItem item) {
        if (status != OrderStatus.CREATED) {
            throw new BusinessException("订单已确认,无法添加商品");
        }
        
        items.add(item);
        calculateTotal();
    }
    
    public void confirmOrder() {
        if (items.isEmpty()) {
            throw new BusinessException("订单必须包含至少一个商品");
        }
        
        this.status = OrderStatus.CONFIRMED;
        // 发送确认事件
        publishEvent(new OrderConfirmedEvent(orderId));
    }
    
    public void processPayment(Payment payment) {
        if (status != OrderStatus.CONFIRMED) {
            throw new BusinessException("只有确认状态的订单才能处理支付");
        }
        
        this.payment = payment;
        this.status = OrderStatus.PAID;
        // 发送支付成功事件
        publishEvent(new PaymentProcessedEvent(orderId));
    }
    
    public void cancelOrder() {
        if (status == OrderStatus.PAID || status == OrderStatus.SHIPPED) {
            throw new BusinessException("已支付或已发货的订单无法取消");
        }
        
        this.status = OrderStatus.CANCELLED;
        // 发送取消事件
        publishEvent(new OrderCancelledEvent(orderId));
    }
    
    private void calculateTotal() {
        this.totalAmount = items.stream()
            .map(item -> item.getPrice().multiply(BigDecimal.valueOf(item.getQuantity())))
            .reduce(BigDecimal.ZERO, BigDecimal::add);
    }
    
    // Getter方法
    public String getOrderId() { return orderId; }
    public OrderStatus getStatus() { return status; }
    public List<OrderItem> getItems() { return new ArrayList<>(items); }
    public BigDecimal getTotalAmount() { return totalAmount; }
}

事件驱动通信

在微服务架构中,不同服务之间通过事件进行异步通信:

// 事件定义
public class OrderEvents {
    
    // 订单创建事件
    public static class OrderCreatedEvent {
        private final String orderId;
        private final String userId;
        private final List<OrderItem> items;
        private final LocalDateTime createdTime;
        
        public OrderCreatedEvent(String orderId, String userId, 
                               List<OrderItem> items) {
            this.orderId = orderId;
            this.userId = userId;
            this.items = items;
            this.createdTime = LocalDateTime.now();
        }
        
        // Getters
        public String getOrderId() { return orderId; }
        public String getUserId() { return userId; }
        public List<OrderItem> getItems() { return new ArrayList<>(items); }
    }
    
    // 订单确认事件
    public static class OrderConfirmedEvent {
        private final String orderId;
        private final LocalDateTime confirmedTime;
        
        public OrderConfirmedEvent(String orderId) {
            this.orderId = orderId;
            this.confirmedTime = LocalDateTime.now();
        }
        
        // Getters
        public String getOrderId() { return orderId; }
    }
    
    // 支付处理事件
    public static class PaymentProcessedEvent {
        private final String orderId;
        private final BigDecimal amount;
        private final LocalDateTime processedTime;
        
        public PaymentProcessedEvent(String orderId, BigDecimal amount) {
            this.orderId = orderId;
            this.amount = amount;
            this.processedTime = LocalDateTime.now();
        }
        
        // Getters
        public String getOrderId() { return orderId; }
        public BigDecimal getAmount() { return amount; }
    }
}

代码实现最佳实践

Repository模式实现

// 聚合根Repository接口
public interface OrderRepository {
    void save(Order order);
    Order findById(String orderId);
    List<Order> findByUserId(String userId);
    void delete(String orderId);
}

// Repository实现
@Repository
public class OrderRepositoryImpl implements OrderRepository {
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @Override
    public void save(Order order) {
        // 使用JDBC或ORM框架保存订单
        String sql = "INSERT INTO orders (order_id, user_id, status, total_amount, created_time) VALUES (?, ?, ?, ?, ?)";
        jdbcTemplate.update(sql, 
            order.getOrderId(),
            order.getUserId(),
            order.getStatus().name(),
            order.getTotalAmount(),
            order.getOrderDate()
        );
        
        // 保存订单项
        saveOrderItems(order.getItems(), order.getOrderId());
    }
    
    @Override
    public Order findById(String orderId) {
        // 根据ID查询订单
        String sql = "SELECT * FROM orders WHERE order_id = ?";
        RowMapper<Order> rowMapper = new OrderRowMapper();
        return jdbcTemplate.queryForObject(sql, rowMapper, orderId);
    }
    
    private void saveOrderItems(List<OrderItem> items, String orderId) {
        // 保存订单项
        for (OrderItem item : items) {
            String sql = "INSERT INTO order_items (order_id, product_id, quantity, price) VALUES (?, ?, ?, ?)";
            jdbcTemplate.update(sql, orderId, item.getProductId(), 
                item.getQuantity(), item.getPrice());
        }
    }
}

领域服务实现

// 领域服务 - 订单处理服务
@Service
public class OrderProcessingService {
    
    @Autowired
    private OrderRepository orderRepository;
    
    @Autowired
    private InventoryService inventoryService;
    
    @Autowired
    private PaymentService paymentService;
    
    // 处理订单创建
    public Order createOrder(CreateOrderRequest request) {
        // 1. 验证用户
        validateUser(request.getUserId());
        
        // 2. 预留库存
        if (!reserveInventory(request.getItems())) {
            throw new BusinessException("库存不足");
        }
        
        // 3. 创建订单聚合根
        Order order = new Order(request.getOrderId(), request.getUserId());
        for (OrderItemRequest item : request.getItems()) {
            order.addItem(new OrderItem(item.getProductId(), item.getQuantity(), 
                                     item.getPrice()));
        }
        
        // 4. 保存订单
        orderRepository.save(order);
        
        // 5. 发布事件
        publishEvent(new OrderCreatedEvent(request.getOrderId(), 
                                         request.getUserId(), 
                                         request.getItems()));
        
        return order;
    }
    
    private boolean reserveInventory(List<OrderItemRequest> items) {
        for (OrderItemRequest item : items) {
            if (!inventoryService.reserveStock(item.getProductId(), item.getQuantity())) {
                return false;
            }
        }
        return true;
    }
    
    private void validateUser(String userId) {
        // 用户验证逻辑
        if (userId == null || userId.isEmpty()) {
            throw new BusinessException("用户ID不能为空");
        }
    }
}

异常处理机制

// 业务异常类
public class BusinessException extends RuntimeException {
    private final String errorCode;
    private final Object[] params;
    
    public BusinessException(String message) {
        super(message);
        this.errorCode = "BUSINESS_ERROR";
        this.params = new Object[0];
    }
    
    public BusinessException(String errorCode, String message, Object... params) {
        super(message);
        this.errorCode = errorCode;
        this.params = params;
    }
    
    // Getters
    public String getErrorCode() { return errorCode; }
    public Object[] getParams() { return params; }
}

// 异常处理器
@RestControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(BusinessException.class)
    public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException ex) {
        ErrorResponse error = new ErrorResponse(
            ex.getErrorCode(),
            ex.getMessage(),
            Arrays.asList(ex.getParams())
        );
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error);
    }
    
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleGeneralException(Exception ex) {
        ErrorResponse error = new ErrorResponse(
            "INTERNAL_ERROR",
            "系统内部错误",
            Collections.emptyList()
        );
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
    }
}

架构设计模式

CQRS模式应用

// 命令模型
public class CreateOrderCommand {
    private final String orderId;
    private final String userId;
    private final List<OrderItem> items;
    
    public CreateOrderCommand(String orderId, String userId, List<OrderItem> items) {
        this.orderId = orderId;
        this.userId = userId;
        this.items = items;
    }
    
    // Getters
    public String getOrderId() { return orderId; }
    public String getUserId() { return userId; }
    public List<OrderItem> getItems() { return new ArrayList<>(items); }
}

// 查询模型
public class OrderQueryModel {
    private final String orderId;
    private final String userId;
    private final OrderStatus status;
    private final BigDecimal totalAmount;
    private final LocalDateTime createdTime;
    
    // 构造函数和Getters
    public OrderQueryModel(String orderId, String userId, OrderStatus status, 
                          BigDecimal totalAmount, LocalDateTime createdTime) {
        this.orderId = orderId;
        this.userId = userId;
        this.status = status;
        this.totalAmount = totalAmount;
        this.createdTime = createdTime;
    }
    
    // Getters
    public String getOrderId() { return orderId; }
    public String getUserId() { return userId; }
    public OrderStatus getStatus() { return status; }
    public BigDecimal getTotalAmount() { return totalAmount; }
    public LocalDateTime getCreatedTime() { return createdTime; }
}

// 查询服务
@Service
public class OrderQueryService {
    
    @Autowired
    private OrderRepository orderRepository;
    
    public List<OrderQueryModel> findOrdersByUserId(String userId) {
        List<Order> orders = orderRepository.findByUserId(userId);
        return orders.stream()
            .map(order -> new OrderQueryModel(
                order.getOrderId(),
                order.getUserId(),
                order.getStatus(),
                order.getTotalAmount(),
                order.getOrderDate()
            ))
            .collect(Collectors.toList());
    }
}

事件溯源模式

// 事件存储
public class EventStore {
    
    private final List<Event> events = new ArrayList<>();
    
    public void save(Event event) {
        events.add(event);
        // 持久化到数据库或消息队列
        persistEvent(event);
    }
    
    public List<Event> getEvents(String aggregateId) {
        return events.stream()
            .filter(event -> event.getAggregateId().equals(aggregateId))
            .collect(Collectors.toList());
    }
}

// 事件聚合根
public class OrderWithEvents {
    private final String orderId;
    private final List<Event> events = new ArrayList<>();
    
    public void apply(Event event) {
        events.add(event);
        // 根据事件更新状态
        updateStateFromEvent(event);
    }
    
    private void updateStateFromEvent(Event event) {
        // 根据不同类型的事件更新聚合根状态
        if (event instanceof OrderCreatedEvent) {
            // 处理订单创建事件
        } else if (event instanceof OrderConfirmedEvent) {
            // 处理订单确认事件
        }
    }
}

测试策略

单元测试示例

// 聚合根单元测试
@SpringBootTest
public class OrderAggregateTest {
    
    @Test
    public void testCreateOrderWithItems() {
        // Given
        String orderId = "ORDER-001";
        String userId = "USER-001";
        
        OrderAggregate order = new OrderAggregate(orderId, userId);
        
        OrderItem item1 = new OrderItem("PROD-001", 2, new BigDecimal("100.00"));
        OrderItem item2 = new OrderItem("PROD-002", 1, new BigDecimal("50.00"));
        
        // When
        order.addItem(item1);
        order.addItem(item2);
        order.confirmOrder();
        
相关推荐
广告位招租

相似文章

    评论 (0)

    0/2000