设计模式学习:2、状态模式实现订单状态流转

支付场景中的状态流转

在开发电商支付模块时,我们常遇到这样的状态流转需求:

  • 订单需要经历 待支付支付中支付成功/失败退款处理 的完整生命周期。
  • 不同状态下可执行的操作不同(例如只有支付成功才能退款)。
  • 状态转换需要触发附加操作(支付成功要发通知、更新库存)。

传统的 if-elseswitch 实现方式会导致:

  • 代码臃肿,维护困难
  • 状态转换逻辑分散
  • 新增状态需要修改大量现有代码

此时,状态模式(State Pattern)是这些问题的最佳解决方案。

状态模式核心思想

通过将状态抽象为独立类,实现两大关键特性:

  1. 行为状态化 :不同状态下相同的操作产生不同结果
  2. 转换自动化 :状态对象自行决定下一个状态

状态模式实现

  1. 状态接口设计
csharp 复制代码
// 订单状态抽象接口
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);
}
  1. 具体状态类实现
    待支付状态:
csharp 复制代码
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("待支付订单不能退款");
    }
}

支付中状态:

csharp 复制代码
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("支付未完成不能退款");
    }
}

支付成功状态:

csharp 复制代码
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());
    }
}

退款中状态:

csharp 复制代码
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("退款处理中,不可重复退款");
    }
}

退款完成状态:

csharp 复制代码
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("订单已退款,无需退款");
    }
}

订单取消状态:

csharp 复制代码
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("订单已取消,无需退款");
    }
}

完整状态流转示例

csharp 复制代码
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

相关推荐
wearegogog1237 小时前
C# .NET 文件比较工具 WinForms
开发语言·c#·.net
学以智用8 小时前
.NET Core Swagger 超详细讲解(从入门到企业级)
后端·.net
qq_2975746711 小时前
设计模式系列文章(基础篇第19篇):中介者模式——封装交互关系,解耦网状依赖
设计模式·交互·中介者模式
AI大法师12 小时前
老牌媒体怎么从“出版物更新”走到“品牌系统升级”
大数据·人工智能·设计模式·新媒体运营
野生技术架构师12 小时前
Java 23 种设计模式:从踩坑到精通 —— 开篇及系列介绍
java·开发语言·设计模式
艾利克斯冰12 小时前
Java设计模式-创建型模式(更新完成)
设计模式
王_teacher13 小时前
23种设计模式之工厂模式
设计模式·软件工程·简单工厂模式·工厂方法模式·抽象工厂模式
geovindu13 小时前
python:Coroutines Pattern
开发语言·python·设计模式·协程模式
云中小生14 小时前
Scrutor:.NET 依赖注入自动化的优雅实现
c#·.net
步步为营DotNet14 小时前
Semantic Kernel 在.NET AI 开发中的深度探索与实践
人工智能·.net