如何优雅地实现枚举状态转换?一个实际案例解析

在软件开发中,我们经常需要处理不同系统或模块间的状态转换。今天,我将通过一个电商订单与物流状态的转换案例,展示如何优雅地实现枚举间的互相转换。

场景描述

假设我们有一个电商系统,包含两个核心状态枚举:

  1. 订单状态(OrderStatusEnum) - 描述订单在电商系统中的生命周期
  2. 物流状态(ShippingStatusEnum) - 描述订单在物流系统中的流转状态

这两个状态密切相关但又不完全相同,我们需要在它们之间建立转换关系。

枚举定义

1. 订单状态枚举

/**
 * 订单状态枚举
 */
public enum OrderStatusEnum {
    UNPAID(0, "待支付"),
    PAID(1, "已支付"),
    PACKAGED(2, "已打包"),
    SHIPPED(3, "已发货"),
    DELIVERED(4, "已送达"),
    COMPLETED(5, "已完成"),
    CANCELLED(10, "已取消"),
    REFUNDING(11, "退款中"),
    REFUNDED(12, "已退款");

    private final int code;
    private final String description;

    OrderStatusEnum(int code, String description) {
        this.code = code;
        this.description = description;
    }

    // 根据code获取枚举实例
    public static OrderStatusEnum fromCode(int code) {
        for (OrderStatusEnum status : values()) {
            if (status.code == code) {
                return status;
            }
        }
        throw new IllegalArgumentException("无效的订单状态码: " + code);
    }

    // 转换为物流状态
    public ShippingStatusEnum toShippingStatus() {
        switch (this) {
            case UNPAID:
            case PAID:
            case CANCELLED:
            case REFUNDING:
            case REFUNDED:
                return null; // 这些订单状态没有对应的物流状态
            case PACKAGED:
                return ShippingStatusEnum.PREPARING;
            case SHIPPED:
                return ShippingStatusEnum.IN_TRANSIT;
            case DELIVERED:
                return ShippingStatusEnum.DELIVERED;
            case COMPLETED:
                return ShippingStatusEnum.COMPLETED;
            default:
                throw new IllegalStateException("未知的订单状态: " + this);
        }
    }

    // getters
    public int getCode() { return code; }
    public String getDescription() { return description; }
}

2. 物流状态枚举

/**
 * 物流状态枚举
 */
public enum ShippingStatusEnum {
    PREPARING(1, "准备中"),
    IN_TRANSIT(2, "运输中"),
    DELIVERED(3, "已送达"),
    COMPLETED(4, "已完成"),
    RETURNING(10, "退货中"),
    RETURNED(11, "已退货");

    private final int code;
    private final String description;

    ShippingStatusEnum(int code, String description) {
        this.code = code;
        this.description = description;
    }

    // 根据code获取枚举实例
    public static ShippingStatusEnum fromCode(int code) {
        for (ShippingStatusEnum status : values()) {
            if (status.code == code) {
                return status;
            }
        }
        throw new IllegalArgumentException("无效的物流状态码: " + code);
    }

    // 转换为订单状态
    public OrderStatusEnum toOrderStatus() {
        switch (this) {
            case PREPARING:
                return OrderStatusEnum.PACKAGED;
            case IN_TRANSIT:
                return OrderStatusEnum.SHIPPED;
            case DELIVERED:
                return OrderStatusEnum.DELIVERED;
            case COMPLETED:
                return OrderStatusEnum.COMPLETED;
            case RETURNING:
                return OrderStatusEnum.REFUNDING;
            case RETURNED:
                return OrderStatusEnum.REFUNDED;
            default:
                throw new IllegalStateException("未知的物流状态: " + this);
        }
    }

    // getters
    public int getCode() { return code; }
    public String getDescription() { return description; }
}

关键设计点解析

  1. 状态映射关系

    • 不是所有订单状态都有对应的物流状态(如待支付、已取消等)
    • 物流状态可能触发订单状态的变更(如退货中对应退款中)
  2. 转换方法设计

    • 每个枚举类内部实现转换方法,知道如何转换为另一种状态
    • 方法命名直观:toShippingStatus()toOrderStatus()
  3. null值处理

    • 当没有对应状态时返回null,调用方需要处理这种情况
  4. 异常处理

    • 对非法状态码抛出明确的异常信息

使用示例

// 订单状态转物流状态
OrderStatusEnum orderStatus = OrderStatusEnum.SHIPPED;
ShippingStatusEnum shippingStatus = orderStatus.toShippingStatus();
System.out.println("订单状态: " + orderStatus.getDescription() 
    + " → 物流状态: " + (shippingStatus != null ? shippingStatus.getDescription() : "无"));

// 物流状态转订单状态
ShippingStatusEnum shippingStatus = ShippingStatusEnum.RETURNING;
OrderStatusEnum orderStatus = shippingStatus.toOrderStatus();
System.out.println("物流状态: " + shippingStatus.getDescription() 
    + " → 订单状态: " + orderStatus.getDescription());

最佳实践建议

  1. 保持转换逻辑简单:如果转换逻辑变得复杂,考虑引入状态模式

  2. 文档化映射关系:在枚举类或项目文档中明确记录状态映射关系

  3. 单元测试:为状态转换编写单元测试,确保转换逻辑正确

  4. 考虑性能:对于高频调用的场景,可以缓存转换结果

  5. 扩展性:设计时考虑未来可能新增的状态

总结

通过在枚举内部实现状态转换方法,我们实现了:

  • 高内聚的设计:转换逻辑与状态定义在一起
  • 易于维护:状态变更时只需修改一处
  • 类型安全:编译时检查状态转换
  • 代码清晰:直观的转换方法调用

这种模式不仅适用于订单和物流状态,还可以应用于各种需要状态转换的场景,如工作流状态、支付状态等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值