DDD | 02-电商相关值对象

创建一个商品详情值对象(ProductDetailVO)。这个值对象将封装一个在线商店中商品的所有关键信息,包括但不限于商品ID、名称、描述、价格、库存量、分类、图片URL等。


/**
* 这个ProductDetailVO类设计用于封装电商平台中商品的详细信息,便于在服务间传递和展示商品数据。
* 它确保了数据的一致性和完整性,同时也提供了必要的getter方法以便访问其属性。
* 通过重写equals和hashCode方法,使得基于商品ID的比较逻辑得以正确执行,这对于商品管理、购物车功能等电商应用中的常见操作至关重要。
*/

public class ProductDetailVO {

    private final Long productId; // 商品ID
    private final String productName; // 商品名称
    private final String productDescription; // 商品描述
    private final BigDecimal price; // 商品价格
    private final Integer stockQuantity; // 库存数量
    private final String category; // 商品类别
    private final List<String> imageUrls; // 商品图片URL列表
    private final String brand; // 品牌
    private final Boolean isActive; // 商品是否上架销售

    /**
     * 构造一个新的商品详情值对象。
     *
     * @param productId        商品ID
     * @param productName      商品名称
     * @param productDescription 商品描述
     * @param price            商品价格
     * @param stockQuantity    库存数量
     * @param category         商品类别
     * @param imageUrls        商品图片URL列表
     * @param brand            品牌
     * @param isActive         商品是否上架销售
     */
    public ProductDetailVO(Long productId, String productName, String productDescription, 
                           BigDecimal price, Integer stockQuantity, String category, 
                           List<String> imageUrls, String brand, Boolean isActive) {
        if (productId == null || productName == null || productName.trim().isEmpty() || 
            price == null || stockQuantity == null || category == null || category.trim().isEmpty() ||
            imageUrls == null || imageUrls.isEmpty() || brand == null || brand.trim().isEmpty()) {
            throw new IllegalArgumentException("Mandatory fields cannot be null or empty.");
        }
        this.productId = productId;
        this.productName = productName.trim();
        this.productDescription = productDescription;
        this.price = price;
        this.stockQuantity = stockQuantity;
        this.category = category.trim();
        this.imageUrls = new ArrayList<>(imageUrls); // 防止外部修改
        this.brand = brand.trim();
        this.isActive = isActive != null ? isActive : true; // 默认上架销售
    }

    // Getter methods
    public Long getProductId() { return productId; }
    public String getProductName() { return productName; }
    public String getProductDescription() { return productDescription; }
    public BigDecimal getPrice() { return price; }
    public Integer getStockQuantity() { return stockQuantity; }
    public String getCategory() { return category; }
    public List<String> getImageUrls() { return new ArrayList<>(imageUrls); } // 返回副本防止外部修改
    public String getBrand() { return brand; }
    public Boolean getIsActive() { return isActive; }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        ProductDetailVO that = (ProductDetailVO) obj;
        return productId.equals(that.productId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(productId);
    }

    /**
     * 提供一个友好的字符串表示形式,概述商品的基本信息。
     *
     * @return 字符串表示形式,如 "Product: iPhone 13, Price: $999, Stock: 100, Category: Electronics"
     */
    @Override
    public String toString() {
        return "Product: " + productName + ", Price: $" + price + ", Stock: " + stockQuantity + 
               ", Category: " + category;
    }
}

创建一个订单详情值对象(OrderDetailVO)。这个值对象将封装关于用户下单后订单的详细信息,包括订单ID、用户信息、商品列表(每个商品及其数量)、订单总价、订单状态、下单时间、预计发货日期等。

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

/**
* 这个OrderDetailVO类设计用于电商系统中处理订单相关的业务逻辑,
* 如订单查询、状态更新等。它整合了用户信息、商品列表及其数量、财务信息以及物流预期,
* 为订单管理提供了全面的数据视图。通过使用值对象的方式,确保了数据的封装性和安全性。
*/
public class OrderDetailVO {

    private final Long orderId; // 订单ID
    private final UserVO user; // 用户信息值对象
    private final List<OrderItemVO> items; // 订单中的商品列表及各自数量
    private final BigDecimal totalPrice; // 订单总金额
    private final String orderStatus; // 订单状态,如"待支付"、"已支付"、"已发货"、"已完成"、"已取消"
    private final LocalDateTime orderTime; // 下单时间
    private final LocalDateTime estimatedDeliveryDate; // 预计发货日期

    /**
     * 构造一个新的订单详情值对象。
     *
     * @param orderId                订单ID
     * @param user                   用户信息
     * @param items                  订单中的商品列表及各自数量
     * @param totalPrice             订单总金额
     * @param orderStatus            订单状态
     * @param orderTime              下单时间
     * @param estimatedDeliveryDate  预计发货日期
     */
    public OrderDetailVO(Long orderId, UserVO user, List<OrderItemVO> items, 
                         BigDecimal totalPrice, String orderStatus, 
                         LocalDateTime orderTime, LocalDateTime estimatedDeliveryDate) {
        if (orderId == null || user == null || items == null || items.isEmpty() || 
            totalPrice == null || orderStatus == null || orderStatus.trim().isEmpty() ||
            orderTime == null) {
            throw new IllegalArgumentException("Mandatory fields cannot be null or empty.");
        }
        this.orderId = orderId;
        this.user = user;
        this.items = new ArrayList<>(items); // 防止外部修改
        this.totalPrice = totalPrice;
        this.orderStatus = orderStatus.trim();
        this.orderTime = orderTime;
        this.estimatedDeliveryDate = estimatedDeliveryDate;
    }

    // Getter methods
    public Long getOrderId() { return orderId; }
    public UserVO getUser() { return user; }
    public List<OrderItemVO> getItems() { return new ArrayList<>(items); } // 返回副本防止外部修改
    public BigDecimal getTotalPrice() { return totalPrice; }
    public String getOrderStatus() { return orderStatus; }
    public LocalDateTime getOrderTime() { return orderTime; }
    public LocalDateTime getEstimatedDeliveryDate() { return estimatedDeliveryDate; }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        OrderDetailVO that = (OrderDetailVO) obj;
        return orderId.equals(that.orderId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(orderId);
    }

    /**
     * 提供一个友好的字符串表示形式,概述订单的基本信息。
     *
     * @return 字符串表示形式,如 "Order ID: 12345, User: John Doe, Total: $999, Status: Paid, Ordered on: 2023-04-01"
     */
    @Override
    public String toString() {
        return "Order ID: " + orderId + ", User: " + user.getUsername() + ", Total: $" + totalPrice + 
               ", Status: " + orderStatus + ", Ordered on: " + orderTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
    }
}

// 假设的订单商品详情值对象
class OrderItemVO {
    private final ProductDetailVO product; // 商品详情
    private final Integer quantity; // 商品数量

    public OrderItemVO(ProductDetailVO product, Integer quantity) {
        this.product = product;
        this.quantity = quantity;
    }

    // Getter methods
    public ProductDetailVO getProduct() { return product; }
    public Integer getQuantity() { return quantity; }
}

// 假设的用户值对象
class UserVO {
    private final String username; // 用户名

    public UserVO(String username) {
        this.username = username;
    }

    // Getter method
    public String getUsername() { return username; }
}


创建一个与促销活动相关的值对象——优惠券值对象(CouponVO)。此值对象将包含有关优惠券的所有关键信息,比如优惠券ID、名称、类型(满减、折扣、固定金额减免)、面额、适用条件、有效期、状态(可使用、已使用、已过期)以及关联的用户或用户群体。

import java.time.LocalDate;

/**
* 这个CouponVO类设计用于管理电商平台中各种促销活动的优惠券,
* 包括定义优惠券的规则、适用范围、有效期等关键属性。
* 它支持灵活的优惠策略配置,同时通过枚举类型保证了类型的准确性和易读性。
* 这样的设计有助于在处理促销活动、计算订单价格以及用户账户管理时提供清晰的数据结构和逻辑。
*/
public class CouponVO {

    private final Long couponId; // 优惠券ID
    private final String couponName; // 优惠券名称
    private final CouponType type; // 优惠券类型
    private final BigDecimal amount; // 优惠金额或折扣率
    private final BigDecimal conditionAmount; // 使用条件(如需满XX元可用)
    private final LocalDate startDate; // 生效日期
    private final LocalDate endDate; // 过期日期
    private final CouponStatus status; // 优惠券状态
    private final UserVO user; // 关联用户
    private final List<UserGroupVO> userGroups; // 可用用户群体列表

    /**
     * 构造一个新的优惠券值对象。
     *
     * @param couponId       优惠券ID
     * @param couponName     优惠券名称
     * @param type           优惠券类型
     * @param amount         优惠金额或折扣率
     * @param conditionAmount 使用条件
     * @param startDate      生效日期
     * @param endDate        过期日期
     * @param status         优惠券状态
     * @param user           关联用户
     * @param userGroups     可用用户群体列表
     */
    public CouponVO(Long couponId, String couponName, CouponType type, BigDecimal amount, 
                    BigDecimal conditionAmount, LocalDate startDate, LocalDate endDate, 
                    CouponStatus status, UserVO user, List<UserGroupVO> userGroups) {
        if (couponId == null || couponName == null || couponName.trim().isEmpty() || 
            type == null || amount == null || startDate == null || endDate == null || 
            status == null) {
            throw new IllegalArgumentException("Mandatory fields cannot be null or empty.");
        }
        if (endDate.isBefore(startDate)) {
            throw new IllegalArgumentException("End date cannot be before start date.");
        }
        this.couponId = couponId;
        this.couponName = couponName.trim();
        this.type = type;
        this.amount = amount;
        this.conditionAmount = conditionAmount;
        this.startDate = startDate;
        this.endDate = endDate;
        this.status = status;
        this.user = user;
        this.userGroups = userGroups != null ? new ArrayList<>(userGroups) : new ArrayList<>(); // 防止外部修改
    }

    // Getter methods
    public Long getCouponId() { return couponId; }
    public String getCouponName() { return couponName; }
    public CouponType getType() { return type; }
    public BigDecimal getAmount() { return amount; }
    public BigDecimal getConditionAmount() { return conditionAmount; }
    public LocalDate getStartDate() { return startDate; }
    public LocalDate getEndDate() { return endDate; }
    public CouponStatus getStatus() { return status; }
    public UserVO getUser() { return user; }
    public List<UserGroupVO> getUserGroups() { return new ArrayList<>(userGroups); } // 返回副本防止外部修改

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        CouponVO couponVO = (CouponVO) obj;
        return couponId.equals(couponVO.couponId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(couponId);
    }

    /**
     * 提供一个友好的字符串表示形式,概述优惠券的基本信息。
     *
     * @return 字符串表示形式,如 "Coupon: Spring Sale, Type: 10% Off, Amount: 50, Valid: 2023-07-01 to 2023-07-8, Status: Active"
     */
    @Override
    public String toString() {
        return "Coupon: " + couponName + ", Type: " + type + ", Amount: " + amount +
               ", Valid: " + startDate + " to " + endDate + ", Status: " + status;
    }

    // 假设的枚举类型
    public enum CouponType {
        DISCOUNT, // 折扣百分比
        FIXED_AMOUNT, // 固定金额减免
        FULL_REDUCTION // 满减
    }

    // 假设的优惠券状态枚举
    public enum CouponStatus {
        ACTIVE, // 可使用
        USED, // 已使用
        EXPIRED // 已过期
    }
}

// 假设的用户群体值对象
class UserGroupVO {
    // 省略具体实现细节
}

设计一个与电商系统中用户购物行为分析相关的值对象——用户行为日志值对象(UserBehaviorLogVO)。这个值对象旨在记录并分析用户的浏览、搜索、加购、购买等行为,为个性化推荐、营销策略优化提供数据支持。

import java.time.LocalDateTime;


/**
* 这个UserBehaviorLogVO类旨在捕捉并封装用户在电商平台上的各种行为,为后续的分析和决策提供数据基础。
* 通过记录详尽的行为日志,电商企业可以深入了解用户偏好、购买习惯等,从而提升用户体验、优化产品推荐算法和营销策略。
* 此外,该值对象的设计考虑了数据的完整性和一致性,确保了行为数据的有效收集和利用。
*/
public class UserBehaviorLogVO {

    private final Long logId; // 行为日志ID
    private final Long userId; // 用户ID
    private final BehaviorType behaviorType; // 行为类型
    private final Long productId; // 关联商品ID
    private final LocalDateTime behaviorTime; // 行为发生时间
    private final String ipAddress; // 用户IP地址
    private final String userAgent; // 用户代理信息(浏览器、设备等)

    /**
     * 构造一个新的用户行为日志值对象。
     *
     * @param logId          日志ID
     * @param userId         用户ID
     * @param behaviorType   行为类型
     * @param productId      商品ID
     * @param behaviorTime   行为发生时间
     * @param ipAddress      用户IP地址
     * @param userAgent      用户代理信息
     */
    public UserBehaviorLogVO(Long logId, Long userId, BehaviorType behaviorType, 
                             Long productId, LocalDateTime behaviorTime, String ipAddress, String userAgent) {
        if (logId == null || userId == null || behaviorType == null || behaviorTime == null) {
            throw new IllegalArgumentException("Mandatory fields cannot be null.");
        }
        this.logId = logId;
        this.userId = userId;
        this.behaviorType = behaviorType;
        this.productId = productId;
        this.behaviorTime = behaviorTime;
        this.ipAddress = ipAddress != null ? ipAddress.trim() : ""; // 防止空字符串问题
        this.userAgent = userAgent != null ? userAgent.trim() : ""; // 同上
    }

    // Getter methods
    public Long getLogId() { return logId; }
    public Long getUserId() { return userId; }
    public BehaviorType getBehaviorType() { return behaviorType; }
    public Long getProductId() { return productId; }
    public LocalDateTime getBehaviorTime() { return behaviorTime; }
    public String getIpAddress() { return ipAddress; }
    public String getUserAgent() { return userAgent; }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        UserBehaviorLogVO that = (UserBehaviorLogVO) obj;
        return logId.equals(that.logId);
    }

    @Override
    public int hashCode() {
        return Objects.hash(logId);
    }

    /**
     * 提供一个友好的字符串表示形式,概述用户行为日志的基本信息。
     *
     * @return 字符串表示形式,如 "User 123 viewed Product 456 at 2023-04-05T14:30:00"
     */
    @Override
    public String toString() {
        return "User " + userId + " " + behaviorType + " Product " + productId + 
               " at " + behaviorTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"));
    }

    // 假设的行为类型枚举
    public enum BehaviorType {
        VIEW, // 浏览
        SEARCH, // 搜索
        ADD_TO_CART, // 加入购物车
        PURCHASE // 购买
    }
}

posted @ 2026-06-24 21:02  ZeroPhix  阅读(7)  评论(0)    收藏  举报