一、状态模式实现方式
- 核心结构
- 状态接口(State):定义状态相关的行为方法。
- 具体状态类(ConcreteState):实现状态接口,封装特定状态下的逻辑。
- 上下文类(Context):维护当前状态引用,委托请求给当前状态对象处理。
- 基础实现示例(以电梯控制为例)
// 状态接口
public interface ElevatorState {
void handle(ElevatorContext context);
}
// 具体状态类:停止状态
public class StopState implements ElevatorState {
@Override
public void handle(ElevatorContext context) {
System.out.println("电梯已停止");
context.setState(new RunningState()); // 切换状态
}
}
// 上下文类
public class ElevatorContext {
private ElevatorState state;
public ElevatorContext(ElevatorState initialState) {
this.state = initialState;
}
public void setState(ElevatorState state) {
this.state = state;
}
public void request() {
state.handle(this); // 委托处理
}
}
- 高级实现技巧
- 状态内部维护上下文:允许状态类直接操作上下文属性(如订单状态流转)。
- 状态工厂优化:集中管理状态对象,避免重复创建。
- 状态共享(单例模式):适用于无状态对象(如红绿灯状态)。
二、测试方法与策略
- 测试目标
- 验证状态切换的正确性(如订单从“待支付”到“已发货”)。
- 确保每个状态下的行为符合预期(如电梯停止时禁止移动)。
- 单元测试工具
使用Mockito框架模拟依赖对象,隔离测试环境:
import static org.mockito.Mockito.*;
// 测试订单状态切换
public class OrderTest {
@Test
public void testOrderStateTransition() {
Order order = new Order();
OrderState initialState = mock(NewState.class);
order.setState(initialState);
// 模拟支付操作触发状态切换
order.pay();
verify(initialState).next(order); // 验证状态转换
assertEquals(PaidState.class, order.getState().getClass());
}
}
- 关键测试场景
- 状态转换验证
使用verify()
检查状态切换方法是否按预期调用。verify(context, times(1)).setState(any(RunningState.class));
- 行为逻辑验证
结合断言(JUnit/Hamcrest)验证输出结果:assertThat(outputStream.toString(), containsString("电梯已停止"));
- 异常处理测试
模拟非法状态操作(如未支付时尝试发货):assertThrows(IllegalStateException.class, () -> order.deliver());
- 参数化测试
覆盖所有状态组合,减少重复代码:
@ParameterizedTest
@EnumSource(ElevatorState.class)
void testAllStates(ElevatorState state) {
ElevatorContext context = new ElevatorContext(state);
context.request();
// 验证状态转换逻辑
}
三、测试最佳实践
- 独立性:每个测试用例初始化独立上下文,避免状态污染。
- 模拟外部依赖:用Mockito替代数据库或网络请求(如模拟订单支付接口)。
- 覆盖率:确保覆盖所有状态转换路径(如红灯→绿灯→黄灯→红灯)。
四、常见问题与解决方案
问题 | 解决方案 |
---|---|
状态切换未触发 | 检查状态类是否正确调用context.setState() 。 |
测试用例间依赖 | 使用@Before 注解重置上下文状态。 |
状态转换逻辑遗漏 | 通过状态机工具(如Spring StateMachine)可视化验证转换规则。 |
五、总结
状态模式通过对象化状态与委托机制实现了行为与状态的解耦,而单元测试则通过模拟框架与断言验证确保了状态转换的可靠性。实际开发中,结合Mockito进行隔离测试,可显著提升代码质量与维护效率。