110、23种设计模式之状态模式(19/23)

一、定义

状态模式是一种行为型设计模式,它允许对象在内部状态改变时改变其行为,使得对象看起来好像修改了它的类。

核心思想:将对象的状态封装为独立的状态类,对象在不同状态下的行为由对应状态类实现,而非通过大量 if-else 或 switch 判断。

二、优缺点

优点:

  • 封装了状态的转换逻辑和不同状态下的行为,符合单一职责原则。

  • 避免了冗长的条件判断语句,代码可读性和可维护性更高。

  • 新增状态时只需扩展状态类,符合开闭原则。

  • 状态转换的逻辑清晰,便于跟踪和调试。

缺点:

  • 状态较多时,会导致状态类数量激增,增加系统复杂度。
  • 状态类之间可能存在依赖关系,增加了维护难度。

三、应用场景

  • 对象的行为依赖于其状态,且状态会频繁变化(如订单状态、支付状态)。
  • 代码中存在大量与状态相关的条件判断(if-else/switch),且难以维护。
  • 需要动态切换对象的行为,且不同行为之间有明确的状态边界(如游戏角色的 "存活""受伤""死亡" 状态)。

四、关键点总结

角色划分:

  • 环境类(Context):维护当前状态,负责状态切换,对外提供交互接口。
  • 抽象状态类(State):定义所有状态的公共行为接口。
  • 具体状态类(ConcreteState):实现抽象状态类,定义特定状态下的行为,并可触发状态转换。

核心逻辑

环境类通过委托当前状态对象处理请求,状态转换由具体状态类内部或环境类控制。

状态独立性

每个状态类专注于自身行为,降低耦合。

五、C# 代码示例

以 "订单状态流转" 为例,订单有 "待支付""已支付""已发货""已完成" 四种状态,每种状态下的行为(如支付、发货、确认收货)不同。

csharp 复制代码
using System;

// 抽象状态类:定义订单状态的行为接口
public abstract class OrderState
{
    protected OrderContext context;

    // 设置环境类引用(用于状态切换)
    public void SetContext(OrderContext context)
    {
        this.context = context;
    }

    // 抽象方法:支付订单
    public abstract void Pay();

    // 抽象方法:发货
    public abstract void Ship();

    // 抽象方法:确认收货
    public abstract void ConfirmReceipt();
}

// 具体状态:待支付
public class PendingPaymentState : OrderState
{
    public override void Pay()
    {
        Console.WriteLine("订单已支付,状态更新为【已支付】");
        // 切换状态为"已支付"
        context.State = new PaidState();
        context.State.SetContext(context);
    }

    public override void Ship()
    {
        Console.WriteLine("错误:订单未支付,无法发货");
    }

    public override void ConfirmReceipt()
    {
        Console.WriteLine("错误:订单未支付,无法确认收货");
    }
}

// 具体状态:已支付
public class PaidState : OrderState
{
    public override void Pay()
    {
        Console.WriteLine("错误:订单已支付,无需重复支付");
    }

    public override void Ship()
    {
        Console.WriteLine("订单已发货,状态更新为【已发货】");
        // 切换状态为"已发货"
        context.State = new ShippedState();
        context.State.SetContext(context);
    }

    public override void ConfirmReceipt()
    {
        Console.WriteLine("错误:订单未发货,无法确认收货");
    }
}

// 具体状态:已发货
public class ShippedState : OrderState
{
    public override void Pay()
    {
        Console.WriteLine("错误:订单已支付,无需重复支付");
    }

    public override void Ship()
    {
        Console.WriteLine("错误:订单已发货,无需重复发货");
    }

    public override void ConfirmReceipt()
    {
        Console.WriteLine("订单已确认收货,状态更新为【已完成】");
        // 切换状态为"已完成"
        context.State = new CompletedState();
        context.State.SetContext(context);
    }
}

// 具体状态:已完成
public class CompletedState : OrderState
{
    public override void Pay()
    {
        Console.WriteLine("错误:订单已完成,无需支付");
    }

    public override void Ship()
    {
        Console.WriteLine("错误:订单已完成,无需发货");
    }

    public override void ConfirmReceipt()
    {
        Console.WriteLine("错误:订单已完成,无需重复确认");
    }
}

// 环境类:订单上下文,维护当前状态并提供交互接口
public class OrderContext
{
    private OrderState _state;

    // 初始状态为"待支付"
    public OrderContext()
    {
        _state = new PendingPaymentState();
        _state.SetContext(this);
    }

    // 当前状态(用于状态切换)
    public OrderState State
    {
        get => _state;
        set => _state = value;
    }

    // 委托当前状态处理支付
    public void PayOrder()
    {
        _state.Pay();
    }

    // 委托当前状态处理发货
    public void ShipOrder()
    {
        _state.Ship();
    }

    // 委托当前状态处理确认收货
    public void ConfirmOrder()
    {
        _state.ConfirmReceipt();
    }
}

// 客户端调用
class Client
{
    static void Main(string[] args)
    {
        OrderContext order = new OrderContext();

        // 模拟订单流程
        order.PayOrder();    // 订单已支付,状态更新为【已支付】
        order.ShipOrder();   // 订单已发货,状态更新为【已发货】
        order.ConfirmOrder();// 订单已确认收货,状态更新为【已完成】
        order.PayOrder();    // 错误:订单已完成,无需支付
    }
}

输出结果:

csharp 复制代码
订单已支付,状态更新为【已支付】  
订单已发货,状态更新为【已发货】  
订单已确认收货,状态更新为【已完成】  
错误:订单已完成,无需支付  

说明:

  • 环境类 OrderContext 封装了订单状态的切换逻辑,客户端只需调用其公共方法(如 PayOrder)。
  • 每个具体状态类(如 PendingPaymentState)实现了对应状态下的行为,并在合适时机触发状态转换。
  • 新增状态(如 "已取消")时,只需添加新的具体状态类,无需修改现有代码,符合开闭原则。
相关推荐
phdsky3 小时前
【设计模式】抽象工厂模式
c++·设计模式·抽象工厂模式
7***37453 小时前
Java设计模式之工厂
java·开发语言·设计模式
雨中飘荡的记忆4 小时前
设计模式之原型模式
设计模式
LengineerC4 小时前
Rust仿node事件总线的简单实现
设计模式·rust
IT永勇6 小时前
C++设计模式-装饰器模式
c++·设计模式·装饰器模式
chinesegf10 小时前
图文并茂的笔记、便签是如何用py开发的
笔记·状态模式
口袋物联12 小时前
设计模式之工厂模式在 C 语言中的应用(含 Linux 内核实例)
linux·c语言·设计模式·简单工厂模式
phdsky15 小时前
【设计模式】建造者模式
c++·设计模式·建造者模式
小毛驴85015 小时前
软件设计模式-装饰器模式
python·设计模式·装饰器模式
phdsky17 小时前
【设计模式】代理模式
设计模式·代理模式