状态模式(State Pattern)是面向对象设计模式中的一种行为模式,它允许一个对象在其内部状态改变时改变它的行为。状态模式的核心意图是将状态相关的逻辑从主类中分离出来,使得每个状态都成为独立的对象,这样可以简化原本复杂的条件语句,并且提高代码的可维护性和扩展性。
意图
允许一个对象在其内部状态改变时改变它的行为。对象看起来似乎修改了它的类。
- 将与特定状态相关的行为局部化,并且将不同状态的行为分割开来。
- 通过切换内部状态来改变对象的行为。
- 让状态转换显得更加明确和可控。
结构
状态模式包含以下几种角色:
- Context(环境类):定义了客户端感兴趣的接口,并维护一个具体状态子类的实例,这个实例定义当前的状态。
- State(抽象状态角色):定义了一个或一组接口,表示支持的所有状态所共有的行为。
- ConcreteState(具体状态角色):每一个具体状态提供一个方法,该方法实现了在Context的一个特定状态下所表现的行为。
结构图
+-------------------+ +------------------+
| Context |-------| State (抽象) |
+-------------------+ +------------------+
| -state: State |<------| + handle() |
+-------------------+ +------------------+
| + request() | | |
+-------------------+ +------------------+
^ ^
| |
| |
+-----------+-----------------+
| |
+---------------v-------------+ +-------v---------+
| ConcreteStateA (具体状态A) | |ConcreteStateB |
+----------------------------+ +---------------+
| + handle() | | + handle() |
+----------------------------+ +---------------+
在这个图中,Context
持有一个State
类型的引用,它可以指向任何具体的State
子类。当Context
的request()
方法被调用时,实际上是由当前状态的handle()
方法来处理请求。State
接口定义了所有具体状态都需要实现的方法。
适用性
- 当一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为时。
- 代码中存在大量与状态相关的条件语句(如if-else或者switch-case),这些语句难以维护和扩展。
- 当状态转换是复杂且具有约束时,状态模式可以帮助清晰地定义并控制状态之间的转换。
状态模式可以用来管理那些需要随时间而变化的对象行为,并且能够帮助我们避免大量的条件分支语句,让代码变得更加清晰和易于理解。在实际应用中,比如工作流引擎、游戏中的角色状态等场景下,状态模式都是十分有用的。
应用举例 (处理订单的状态变化)
状态模式在Java开发中有很多经典的应用场景,其中一个非常典型的例子是处理订单的状态变化。在电子商务系统中,一个订单可能会经历多种状态,如创建、支付、发货、完成和取消等。每个状态下可以执行的操作不同,并且从一种状态到另一种状态的转换规则也可能很复杂。使用状态模式可以很好地管理这种状态的变化。
场景描述
假设我们正在为一个在线购物网站开发后端服务。我们需要处理用户的订单,而订单可能有以下几种状态:
- 新创建(New):用户刚刚下单。
- 已支付(Paid):用户已经付款。
- 已发货(Shipped):商品已经发出。
- 已完成(Completed):用户收到商品并且确认收货。
- 已取消(Cancelled):订单被取消。
对于每种状态,允许的操作是不同的。例如,在"新创建"状态下,用户可以选择支付或取消订单;而在"已支付"状态下,用户不能再次支付,但是可以等待发货或者申请退款。
状态模式实现
定义抽象状态接口
java
public interface OrderState {
void handle(Order order);
}
实现具体状态
java
public class NewOrderState implements OrderState {
@Override
public void handle(Order order) {
System.out.println("Order is in New state. Waiting for payment.");
// 可以进行支付操作
order.setState(new PaidOrderState());
}
}
public class PaidOrderState implements OrderState {
@Override
public void handle(Order order) {
System.out.println("Order is paid. Preparing to ship.");
// 可以进行发货操作
order.setState(new ShippedOrderState());
}
}
// 其他状态类省略...
定义环境类(订单)
java
public class Order {
private OrderState state;
public Order() {
this.state = new NewOrderState(); // 默认为新创建状态
}
public void setState(OrderState state) {
this.state = state;
}
public void request() {
state.handle(this);
}
}
使用示例
java
public class Client {
public static void main(String[] args) {
Order order = new Order();
order.request(); // 输出: Order is in New state. Waiting for payment.
order.request(); // 输出: Order is paid. Preparing to ship.
// 更多的状态转换...
}
}
在这个简单的例子中,Order
对象根据当前的状态来决定如何处理请求。当调用request()
方法时,实际是由当前状态的handle()
方法来处理逻辑。这样做的好处是可以将不同状态下的行为封装起来,避免了复杂的条件判断,并且易于添加新的状态或修改现有状态的行为。