状态模式
状态模式是一种行为设计模式,它使对象在其内部状态改变时改变其行为,从而让对象看起来好像修改了它的类。这种模式主要用于处理状态转换逻辑复杂的场景,通过封装不同状态下的行为到独立的类中,使得状态转换更加清晰和易于维护。
解决问题
解决的问题
主要解决的是当控制一个对象状态转化的条件表达式过于复杂时的情况,把状态的判断逻辑转移到表示不同状态的一系列类当中,可以把复杂的判断逻辑简化。
类图
主要角色
- 上下文(Context):也称为环境类,它是拥有状态的对象。上下文维护一个
State
对象,该对象定义了当前的状态,并且可以通过上下文的请求来改变状态。 - 抽象状态(State):定义一个接口以封装与上下文的一个特定状态相关的行为。
- 具体状态(ConcreteState):实现
State
接口的具体类,每一个具体状态类对应上下文的一个具体状态,并且在该状态下实现对应的行为。
优缺点
优点
- 封装状态转换:将状态的转换逻辑放入具体状态类中,使得状态转换变得清晰和有条理。
- 遵循开闭原则:新增状态类时不需要修改现有的状态类和上下文类,只需添加新的具体状态类即可。
- 更好的维护性:状态和行为的分离使代码更加模块化,便于理解和维护。
缺点
- 状态类增加:随着状态的增加,会导致状态类的数量也增多,使代码变得复杂。
- 上下文类可能变得臃肿:上下文需要维护所有状态的实例,可能导致内存开销的增加。
适用场景
状态模式适用于以下场景:
- 对象的行为依赖于其状态,并且需要在运行时根据状态改变行为。
- 状态的逻辑复杂,使用状态模式可以将复杂的状态逻辑分解为多个独立的状态类。
- 状态的数量较少,不容易导致类的膨胀。
应用场景
- 订单系统:订单从创建到完成会经历多种状态(如待支付、已支付、已发货、已完成等),每个状态下的处理逻辑不同,可以使用状态模式来管理这些状态和行为。
- 用户认证流程:用户的认证状态(未登录、已登录、登录过期等)影响着用户能访问的资源,通过状态模式可以灵活地处理不同状态下的权限控制。
- 电梯控制系统:电梯根据楼层请求和内部状态(如开门、关门、上行、下行、停止等)改变行为,状态模式能很好地处理这类状态转换逻辑。
示例
java
// 状态接口
interface OrderState {
void handleOrder(OrderContext context);
}
// 具体状态类:新建状态
class NewOrderState implements OrderState {
@Override
public void handleOrder(OrderContext context) {
System.out.println("Order is in new state. Processing new order...");
context.setState(new ProcessingOrderState());
}
}
// 具体状态类:处理中状态
class ProcessingOrderState implements OrderState {
@Override
public void handleOrder(OrderContext context) {
System.out.println("Order is in processing state. Processing order...");
context.setState(new ShippedOrderState());
}
}
// 具体状态类:已发货状态
class ShippedOrderState implements OrderState {
@Override
public void handleOrder(OrderContext context) {
System.out.println("Order is shipped. Completing order...");
context.setState(new DeliveredOrderState());
}
}
// 具体状态类:已交付状态
class DeliveredOrderState implements OrderState {
@Override
public void handleOrder(OrderContext context) {
System.out.println("Order is delivered. Order complete.");
}
}
// 上下文类
class OrderContext {
private OrderState state;
public OrderContext() {
state = new NewOrderState(); // 初始状态为新建
}
public void setState(OrderState state) {
this.state = state;
}
public void processOrder() {
state.handleOrder(this);
}
}
// 测试状态模式
public class StatePatternDemo {
public static void main(String[] args) {
OrderContext orderContext = new OrderContext();
// 模拟订单处理过程
orderContext.processOrder(); // 新建 -> 处理中
orderContext.processOrder(); // 处理中 -> 已发货
orderContext.processOrder(); // 已发货 -> 已交付
}
}