C#设计模式:状态模式
在软件开发中,我们经常会遇到对象的行为取决于其状态的情况。例如,一个订单对象可能处于“待支付”、“已支付”、“已发货”等不同状态,而每个状态下订单的行为(例如是否可以支付、是否可以发货)是不同的。
传统的处理方式是使用大量的 if-else
或 switch-case
语句来判断对象的状态,然后执行相应的行为。这种方式虽然直观,但随着状态数量的增加,代码会变得臃肿、难以维护,并且违背了开放-封闭原则。
状态模式 (State Pattern) 提供了一种优雅的解决方案,它将对象的状态抽象成独立的类,并将对象的行为委托给当前状态对象。这样,对象就可以在不同的状态下表现出不同的行为,而无需修改自身的代码。
一、状态模式的结构
状态模式主要包含以下几个角色:
- Context(上下文): 定义客户感兴趣的接口,并维护一个具体状态对象的实例,该实例定义了对象的当前状态。
- State(状态): 定义一个接口,用于封装与 Context 的特定状态相关的行为。
- ConcreteState(具体状态): 实现 State 接口,每个具体状态类对应对象的一种状态,并实现该状态下的行为。
二、状态模式的实现
以下是一个简单的 C# 示例,演示如何使用状态模式实现一个订单系统:
// Context 类
public class Order
{
private OrderState _state;
public Order()
{
// 初始状态为待支付
_state = new PendingPaymentState(this);
}
public void SetState(OrderState state)
{
_state = state;
}
public void Pay()
{
_state.Pay();
}
public void Ship()
{
_state.Ship();
}
public void Cancel()
{
_state.Cancel();
}
}
// State 接口
public interface OrderState
{
void Pay();
void Ship();
void Cancel();
}
// 具体状态类:待支付
public class PendingPaymentState : OrderState
{
private Order _order;
public PendingPaymentState(Order order)
{
_order = order;
}
public void Pay()
{
Console.WriteLine("订单支付成功!");
_order.SetState(new PaidState(_order));
}
public void Ship()
{
Console.WriteLine("订单未支付,无法发货!");
}
public void Cancel()
{
Console.WriteLine("订单已取消!");
_order.SetState(new CancelledState(_order));
}
}
// 具体状态类:已支付
public class PaidState : OrderState
{
private Order _order;
public PaidState(Order order)
{
_order = order;
}
public void Pay()
{
Console.WriteLine("订单已支付,无需重复支付!");
}
public void Ship()
{
Console.WriteLine("订单发货成功!");
_order.SetState(new ShippedState(_order));
}
public void Cancel()
{
Console.WriteLine("订单已支付,无法取消!");
}
}
// 具体状态类:已发货
public class ShippedState : OrderState
{
private Order _order;
public ShippedState(Order order)
{
_order = order;
}
public void Pay()
{
Console.WriteLine("订单已发货,无法支付!");
}
public void Ship()
{
Console.WriteLine("订单已发货,无需重复发货!");
}
public void Cancel()
{
Console.WriteLine("订单已发货,无法取消!");
}
}
// 具体状态类:已取消
public class CancelledState : OrderState
{
private Order _order;
public CancelledState(Order order)
{
_order = order;
}
public void Pay()
{
Console.WriteLine("订单已取消,无法支付!");
}
public void Ship()
{
Console.WriteLine("订单已取消,无法发货!");
}
public void Cancel()
{
Console.WriteLine("订单已取消,无需重复取消!");
}
}
// 客户端代码
class Program
{
static void Main(string[] args)
{
Order order = new Order();
order.Pay(); // 输出:订单支付成功!
order.Ship(); // 输出:订单发货成功!
order.Cancel(); // 输出:订单已发货,无法取消!
}
}
三、状态模式的优点
- 将状态相关的行为局部化: 将与特定状态相关的行为封装在独立的类中,使得代码更加清晰、易于理解和维护。
- 避免使用大量的条件语句: 通过将状态转换逻辑分散到各个状态类中,可以避免使用大量的
if-else
或switch-case
语句,提高代码的可读性和可维护性。 - 方便添加新的状态: 如果需要添加新的状态,只需要创建新的具体状态类,并实现相应的行为即可,无需修改现有的代码,符合开放-封闭原则。
四、状态模式的适用场景
- 对象的行为取决于其状态,并且状态数量较多。
- 需要在运行时根据状态改变对象的行为。
- 需要避免使用大量的条件语句来判断对象的状态。
五、总结
状态模式是一种非常有用的设计模式,它可以帮助我们更好地组织和管理对象的状态和行为。通过将状态抽象成独立的类,并将行为委托给当前状态对象,我们可以使代码更加清晰、易于理解和维护。