110、23种设计模式之状态模式(19/23)
一、定义
状态模式是一种行为型设计模式,它允许对象在内部状态改变时改变其行为,使得对象看起来好像修改了它的类。
核心思想:将对象的状态封装为独立的状态类,对象在不同状态下的行为由对应状态类实现,而非通过大量 if-else 或 switch 判断。
二、优缺点
优点:
- 
封装了状态的转换逻辑和不同状态下的行为,符合单一职责原则。
 - 
避免了冗长的条件判断语句,代码可读性和可维护性更高。
 - 
新增状态时只需扩展状态类,符合开闭原则。
 - 
状态转换的逻辑清晰,便于跟踪和调试。
 
缺点:
- 状态较多时,会导致状态类数量激增,增加系统复杂度。
 - 状态类之间可能存在依赖关系,增加了维护难度。
 
三、应用场景
- 对象的行为依赖于其状态,且状态会频繁变化(如订单状态、支付状态)。
 - 代码中存在大量与状态相关的条件判断(if-else/switch),且难以维护。
 - 需要动态切换对象的行为,且不同行为之间有明确的状态边界(如游戏角色的 “存活”“受伤”“死亡” 状态)。
 
四、关键点总结
角色划分:
- 环境类(Context):维护当前状态,负责状态切换,对外提供交互接口。
 - 抽象状态类(State):定义所有状态的公共行为接口。
 - 具体状态类(ConcreteState):实现抽象状态类,定义特定状态下的行为,并可触发状态转换。
 
核心逻辑
环境类通过委托当前状态对象处理请求,状态转换由具体状态类内部或环境类控制。
状态独立性
每个状态类专注于自身行为,降低耦合。
五、C# 代码示例
以 “订单状态流转” 为例,订单有 “待支付”“已支付”“已发货”“已完成” 四种状态,每种状态下的行为(如支付、发货、确认收货)不同。
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();    // 错误:订单已完成,无需支付}
}
输出结果:
订单已支付,状态更新为【已支付】  
订单已发货,状态更新为【已发货】  
订单已确认收货,状态更新为【已完成】  
错误:订单已完成,无需支付  
说明:
- 环境类 OrderContext 封装了订单状态的切换逻辑,客户端只需调用其公共方法(如 PayOrder)。
 - 每个具体状态类(如 PendingPaymentState)实现了对应状态下的行为,并在合适时机触发状态转换。
 - 新增状态(如 “已取消”)时,只需添加新的具体状态类,无需修改现有代码,符合开闭原则。
 

