设计模式学习:2、状态模式实现订单状态流转
支付场景中的状态流转
在开发电商支付模块时,我们常遇到这样的状态流转需求:
- 订单需要经历
待支付
→支付中
→支付成功/失败
→退款处理
的完整生命周期。 - 不同状态下可执行的操作不同(例如只有支付成功才能退款)。
- 状态转换需要触发附加操作(支付成功要发通知、更新库存)。
传统的 if-else
或 switch
实现方式会导致:
- 代码臃肿,维护困难
- 状态转换逻辑分散
- 新增状态需要修改大量现有代码
此时,状态模式(State Pattern)是这些问题的最佳解决方案。
状态模式核心思想
通过将状态抽象为独立类,实现两大关键特性:
- 行为状态化 :不同状态下相同的操作产生不同结果
- 转换自动化 :状态对象自行决定下一个状态
状态模式实现
- 状态接口设计
// 订单状态抽象接口
public interface IOrderState
{
void Process(OrderContext context);
void Cancel(OrderContext context);
void Refund(OrderContext context);
}
// 订单上下文(维护当前状态)
public class OrderContext
{
private IOrderState _currentState;
public string OrderId { get; } = Guid.NewGuid().ToString();
public OrderContext(IOrderState initialState)
{
TransitionTo(initialState);
}
public void TransitionTo(IOrderState state)
{
Console.WriteLine($"订单状态变更:{_currentState?.GetType().Name} → {state.GetType().Name}");
_currentState = state;
}
public void ProcessPayment() => _currentState.Process(this);
public void CancelOrder() => _currentState.Cancel(this);
public void RequestRefund() => _currentState.Refund(this);
}
- 具体状态类实现
待支付状态:
public class PendingState : IOrderState
{
public void Process(OrderContext context)
{
Console.WriteLine("开始支付处理...");
// 调用支付网关接口
context.TransitionTo(new ProcessingState());
}
public void Cancel(OrderContext context)
{
Console.WriteLine("订单已取消");
context.TransitionTo(new CanceledState());
}
public void Refund(OrderContext context)
{
Console.WriteLine("待支付订单不能退款");
throw new InvalidOperationException("待支付订单不能退款");
}
}
支付中状态:
public class ProcessingState : IOrderState
{
public void Process(OrderContext context)
{
Console.WriteLine("支付处理中...");
context.TransitionTo(new PaidState());
}
public void Cancel(OrderContext context)
{
Console.WriteLine("支付处理中,不可取消订单...");
throw new InvalidOperationException("支付处理中,不可取消订单...");
}
public void Refund(OrderContext context)
{
Console.WriteLine("支付未完成不能退款");
throw new InvalidOperationException("支付未完成不能退款");
}
}
支付成功状态:
public class PaidState : IOrderState
{
public void Process(OrderContext context)
{
Console.WriteLine("订单已完成支付");
throw new InvalidOperationException("订单已完成支付");
}
public void Cancel(OrderContext context)
{
Console.WriteLine("已支付订单需走退款流程");
throw new InvalidOperationException("已支付订单需走退款流程");
}
public void Refund(OrderContext context)
{
Console.WriteLine("发起退款申请...");
// 调用退款接口
context.TransitionTo(new RefundingState());
}
}
退款中状态:
public class RefundingState : IOrderState
{
public void Process(OrderContext context)
{
Console.WriteLine("退款处理中...");
context.TransitionTo(new RefundedState());
}
public void Cancel(OrderContext context)
{
Console.WriteLine("退款处理中,不可取消订单...");
throw new InvalidOperationException("退款处理中,不可取消订单...");
}
public void Refund(OrderContext context)
{
Console.WriteLine("退款处理中,不可重复退款");
throw new InvalidOperationException("退款处理中,不可重复退款");
}
}
退款完成状态:
public class RefundedState : IOrderState
{
public void Process(OrderContext context)
{
Console.WriteLine("退款完成,订单已取消");
throw new InvalidOperationException("退款完成,订单已取消");
}
public void Cancel(OrderContext context)
{
Console.WriteLine("订单已退款,无需取消");
throw new InvalidOperationException("订单已退款,无需取消");
}
public void Refund(OrderContext context)
{
Console.WriteLine("订单已退款,无需退款");
throw new InvalidOperationException("订单已退款,无需退款");
}
}
订单取消状态:
public class CanceledState : IOrderState
{
public void Process(OrderContext context)
{
Console.WriteLine("订单已取消,无需支付");
throw new InvalidOperationException("订单已取消,无需支付");
}
public void Cancel(OrderContext context)
{
Console.WriteLine("订单已取消,无需取消");
throw new InvalidOperationException("订单已取消,无需取消");
}
public void Refund(OrderContext context)
{
Console.WriteLine("订单已取消,无需退款");
throw new InvalidOperationException("订单已取消,无需退款");
}
}
完整状态流转示例
var order = new OrderContext(new PendingState());
order.ProcessPayment(); // 进入ProcessingState
order.RequestRefund(); // 输出警告信息
// 模拟支付成功回调
order.TransitionTo(new PaidState());
order.RequestRefund(); // 进入RefundingState
相关代码:https://github.com/huangmingji/design-pattern-learning/tree/main/design-pattern-learning-2
作者:huangmingji
出处:https://www.cnblogs.com/huangmingji/p/18755997
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
扫码关注微信公众号
请我喝一杯蜜雪冰城吧。🧋
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步