大连网站制作报价有名的互联网公司
2026/2/15 21:55:13 网站建设 项目流程
大连网站制作报价,有名的互联网公司,网页制作培训心得,网络营销包括1. 核心概念定义 1.1 聚合#xff08;Aggregate#xff09; 聚合是DDD中的业务一致性边界#xff0c;将相关的实体和值对象组合成一个整体#xff0c;确保聚合内的数据始终保持一致性。 核心原则#xff1a; 聚合内的所有操作都必须通过聚合根进行聚合内的业务规则必须…1. 核心概念定义1.1 聚合Aggregate聚合是DDD中的业务一致性边界将相关的实体和值对象组合成一个整体确保聚合内的数据始终保持一致性。核心原则聚合内的所有操作都必须通过聚合根进行聚合内的业务规则必须得到保证聚合之间通过唯一标识引用不直接关联1.2 聚合根Aggregate Root聚合根是聚合的唯一入口负责维护聚合内的业务规则和数据一致性作为聚合的唯一标识和外部访问点协调聚合内的实体和值对象1.3 实体Entityvs 值对象Value Object特征实体值对象唯一标识有如OrderID无通过属性值唯一可变性可变如订单状态变更不可变如地址修改需创建新对象生命周期独立由聚合根管理依赖于实体无独立生命周期相等性通过ID判断通过属性值判断2. 订单领域聚合设计2.1 订单领域核心元素识别业务场景用户下单流程创建订单包含多个订单项订单有状态待支付、已支付、已取消等订单项包含商品信息、数量、单价订单关联收货地址、支付信息订单金额 所有订单项金额之和2.2 聚合边界划分订单聚合Order Aggregate聚合根Order订单实体OrderItem订单项有唯一标识值对象Address地址、PaymentInfo支付信息、ProductSnapshot商品快照用户聚合User Aggregate聚合根User用户值对象UserProfile用户信息、ContactInfo联系信息商品聚合Product Aggregate聚合根Product商品值对象ProductDetail商品详情、PriceInfo价格信息2.3 订单聚合完整结构包含包含包含包含包含包含关联关联Order聚合根OrderItem实体OrderItem实体Address值对象PaymentInfo值对象ProductSnapshot值对象UserID外部聚合引用PaymentID外部聚合引用3. 聚合根与聚合对象的详细设计3.1 订单聚合根Order3.1.1 核心属性AggregateRootpublicclassOrder{// 聚合根唯一标识privateOrderIDorderId;// 关联外部聚合的ID非直接引用privateUserIDuserId;// 聚合内实体集合privateListOrderItemorderItems;// 聚合内值对象privateAddressshippingAddress;privatePaymentInfopaymentInfo;// 聚合根状态privateOrderStatusstatus;privateBigDecimaltotalAmount;privateLocalDateTimecreatedAt;privateLocalDateTimeupdatedAt;// 构造函数和业务方法...}3.1.2 业务方法确保聚合内一致性// 构造函数创建订单确保订单项数量和金额一致publicOrder(OrderIDorderId,UserIDuserId,ListOrderItemorderItems,AddressshippingAddress){// 业务规则1订单项不能为空if(CollectionUtils.isEmpty(orderItems)){thrownewDomainException(订单项不能为空);}// 业务规则2计算总金额确保与订单项金额一致BigDecimalcalculatedTotalorderItems.stream().map(OrderItem::getTotalPrice).reduce(BigDecimal.ZERO,BigDecimal::add);// 初始化聚合根this.orderIdorderId;this.userIduserId;this.orderItemsnewArrayList(orderItems);this.shippingAddressshippingAddress;this.totalAmountcalculatedTotal;this.statusOrderStatus.CREATED;this.createdAtLocalDateTime.now();this.updatedAtLocalDateTime.now();}// 取消订单更新订单状态确保所有订单项状态一致publicvoidcancel(){// 业务规则只有待支付状态的订单才能取消if(this.status!OrderStatus.CREATED){thrownewDomainException(只有待支付状态的订单才能取消);}// 更新订单状态this.statusOrderStatus.CANCELLED;this.updatedAtLocalDateTime.now();// 无需更新订单项状态因为订单项状态由订单状态驱动}// 添加订单项确保金额一致性publicvoidaddOrderItem(OrderItemorderItem){// 业务规则订单已支付或取消不能添加订单项if(this.status!OrderStatus.CREATED){thrownewDomainException(订单已支付或取消不能添加订单项);}// 添加订单项this.orderItems.add(orderItem);// 更新总金额this.totalAmountthis.totalAmount.add(orderItem.getTotalPrice());this.updatedAtLocalDateTime.now();}3.2 订单项实体OrderItem3.2.1 核心属性publicclassOrderItem{// 订单项唯一标识在聚合内唯一全局唯一需包含OrderIDprivateOrderItemIDorderItemId;// 商品快照值对象记录下单时的商品信息privateProductSnapshotproductSnapshot;// 订单项属性privateIntegerquantity;privateBigDecimalunitPrice;privateBigDecimaltotalPrice;// 构造函数和业务方法...}3.2.2 业务方法// 构造函数确保订单项金额计算正确publicOrderItem(OrderItemIDorderItemId,ProductSnapshotproductSnapshot,Integerquantity){// 业务规则1数量必须大于0if(quantity0){thrownewDomainException(订单项数量必须大于0);}// 业务规则2单价必须大于0if(productSnapshot.getPrice().compareTo(BigDecimal.ZERO)0){thrownewDomainException(商品单价必须大于0);}this.orderItemIdorderItemId;this.productSnapshotproductSnapshot;this.quantityquantity;this.unitPriceproductSnapshot.getPrice();this.totalPricethis.unitPrice.multiply(newBigDecimal(quantity));}// 更新数量确保金额同步更新publicvoidupdateQuantity(IntegernewQuantity){// 业务规则数量必须大于0if(newQuantity0){thrownewDomainException(订单项数量必须大于0);}this.quantitynewQuantity;this.totalPricethis.unitPrice.multiply(newBigDecimal(newQuantity));}3.3 地址值对象Address// 值对象不可变通过属性值判断相等性publicclassAddress{privatefinalStringprovince;privatefinalStringcity;privatefinalStringdistrict;privatefinalStringdetail;privatefinalStringzipCode;privatefinalStringcontactName;privatefinalStringcontactPhone;// 构造函数一次性初始化无setter方法publicAddress(Stringprovince,Stringcity,Stringdistrict,Stringdetail,StringzipCode,StringcontactName,StringcontactPhone){// 业务规则验证if(StringUtils.isBlank(province)){thrownewDomainException(省份不能为空);}// 其他规则验证...this.provinceprovince;this.citycity;this.districtdistrict;this.detaildetail;this.zipCodezipCode;this.contactNamecontactName;this.contactPhonecontactPhone;}// 只提供getter方法无setterpublicStringgetProvince(){returnprovince;}// 其他getter方法...// 值对象相等性判断通过所有属性值比较Overridepublicbooleanequals(Objecto){if(thiso)returntrue;if(onull||getClass()!o.getClass())returnfalse;Addressaddress(Address)o;returnObjects.equals(province,address.province)Objects.equals(city,address.city)Objects.equals(district,address.district)Objects.equals(detail,address.detail)Objects.equals(zipCode,address.zipCode)Objects.equals(contactName,address.contactName)Objects.equals(contactPhone,address.contactPhone);}}4. 聚合根与聚合对象的设计原则4.1 边界设计原则业务一致性优先聚合边界应根据业务规则确定确保同一业务规则内的实体和值对象在同一聚合内避免过大聚合单个聚合包含的实体不应超过10个否则会影响性能和可维护性通过ID引用其他聚合聚合之间不应直接引用而应通过唯一标识关联避免聚合过大4.2 一致性维护原则聚合根负责一致性聚合内的所有业务规则由聚合根维护外部不能直接修改聚合内的实体事务边界与聚合边界一致一个事务只应修改一个聚合避免分布式事务不可变值对象值对象应设计为不可变避免意外修改4.3 访问控制原则外部只能访问聚合根外部系统或其他聚合只能通过聚合根的方法访问聚合内的实体和值对象聚合内实体可直接访问聚合内的实体可以直接访问同一聚合内的其他实体和值对象禁止跨聚合修改一个聚合的方法不应修改另一个聚合的状态5. 聚合根与仓储Repository的关系5.1 仓储设计原则每个聚合根对应一个仓储Order聚合根对应OrderRepositoryUser聚合根对应UserRepository仓储只返回完整聚合仓储的findById方法必须返回完整的聚合根实例包含所有关联的实体和值对象仓储负责聚合的持久化仓储负责将整个聚合保存到数据库或从数据库加载整个聚合5.2 订单仓储接口设计// 只针对聚合根Order的仓储publicinterfaceOrderRepository{// 保存完整聚合voidsave(Orderorder);// 根据聚合根ID加载完整聚合OptionalOrderfindById(OrderIDorderId);// 删除完整聚合voiddelete(Orderorder);// 根据业务条件查询聚合根列表ListOrderfindByUserId(UserIDuserId);ListOrderfindByStatus(OrderStatusstatus);}6. 订单领域聚合的实际应用6.1 创建订单流程// 1. 准备订单数据UserIDuserIdnewUserID(user-123);OrderIDorderIdnewOrderID(order-456);// 2. 创建值对象AddressshippingAddressnewAddress(广东省,深圳市,南山区,科技园,518000,张三,13800138000);ProductSnapshotproductSnapshot1newProductSnapshot(newProductID(product-789),iPhone 15,newBigDecimal(9999),newBigDecimal(9999));ProductSnapshotproductSnapshot2newProductSnapshot(newProductID(product-012),AirPods Pro,newBigDecimal(1999),newBigDecimal(1999));// 3. 创建实体通过聚合根方法而非直接实例化OrderItemorderItem1newOrderItem(newOrderItemID(order-item-345),productSnapshot1,1);OrderItemorderItem2newOrderItem(newOrderItemID(order-item-678),productSnapshot2,2);// 4. 创建聚合根确保聚合内一致性OrderordernewOrder(orderId,userId,Arrays.asList(orderItem1,orderItem2),shippingAddress);// 5. 调用聚合根业务方法order.addOrderItem(newOrderItem(newOrderItemID(order-item-901),productSnapshot1,1));// 6. 保存完整聚合到仓储orderRepository.save(order);6.2 取消订单流程// 1. 从仓储加载完整聚合OptionalOrderorderOptorderRepository.findById(newOrderID(order-456));if(orderOpt.isPresent()){OrderorderorderOpt.get();// 2. 调用聚合根业务方法确保业务规则order.cancel();// 3. 保存更新后的聚合orderRepository.save(order);}7. 聚合设计的常见误区7.1 误区1聚合过大问题将用户、订单、商品都放在同一个聚合内导致聚合过大性能下降解决按业务边界拆分用户、订单、商品分别作为独立聚合通过ID关联7.2 误区2直接关联其他聚合问题订单聚合直接引用User对象导致订单聚合依赖用户聚合的所有变化解决订单聚合只保存UserID需要用户信息时通过UserID查询User聚合7.3 误区3外部直接修改聚合内实体问题外部系统直接修改OrderItem的数量绕过了Order聚合根的业务规则解决将OrderItem的setter方法设为私有只能通过Order的addOrderItem或updateOrderItem方法修改7.4 误区4聚合内实体过多问题一个订单包含数百个订单项导致聚合加载和保存性能下降解决考虑将订单项拆分为独立聚合或使用分页加载8. 总结8.1 聚合根与聚合对象的核心价值业务一致性确保同一业务规则内的数据始终保持一致清晰的边界明确业务领域的划分提高系统的可维护性性能优化减少跨聚合的关联查询提高系统性能可测试性聚合内的业务规则可以独立测试提高代码质量8.2 订单领域的聚合设计总结聚合根聚合内实体聚合内值对象核心业务规则OrderOrderItemAddress、PaymentInfo、ProductSnapshot1. 订单项不能为空2. 订单总金额等于订单项金额之和3. 只有待支付状态的订单才能取消4. 订单项数量必须大于0User-UserProfile、ContactInfo1. 用户名不能为空2. 手机号必须唯一Product-ProductDetail、PriceInfo1. 商品名称不能为空2. 商品价格必须大于0通过合理设计聚合根和聚合对象可以构建出清晰、一致、高性能的DDD领域模型为微服务架构奠定坚实的基础。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询