状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。核心:把每个状态封装成独立类,上下文对象持有状态引用,状态切换委托状态类处理。
适用场景:对象行为依赖状态,大量 if‑else/switch 判断状态分支。
UML 角色
State(抽象状态):定义各状态公共行为接口
ConcreteState(具体状态):实现对应状态下的业务逻辑
Context(上下文):持有当前 State,对外暴露业务方法,负责状态切换
示例场景:电梯状态
电梯 4 种状态:开门、关门、运行、停止 每个状态下:开门、关门、运行、停止动作有不同约束。
/**
* 抽象状态角色:电梯状态
*/
public interface ElevatorState {
// 开门
void open();
// 关门
void close();
// 运行
void run();
// 停止
void stop();
}
/**
* 上下文:电梯对象
*/
class ElevatorContext {
private ElevatorState currentState;
public ElevatorContext(ElevatorState initState) {
this.currentState = initState;
}
// 切换状态
public void setState(ElevatorState state) {
this.currentState = state;
}
// 对外暴露动作,全部委托给状态对象
public void open() {
currentState.open();
}
public void close() {
currentState.close();
}
public void run() {
currentState.run();
}
public void stop() {
currentState.stop();
}
}
/**
* 具体状态:开门状态
*/
class OpenState implements ElevatorState {
private final ElevatorContext context;
public OpenState(ElevatorContext context) {
this.context = context;
}
@Override
public void open() {
System.out.println("【开门状态】电梯已经是开门,无需重复开门");
}
@Override
public void close() {
System.out.println("【开门状态】执行关门,切换到关门状态");
context.setState(new CloseState(context));
}
@Override
public void run() {
System.out.println("【开门状态】禁止运行!门还开着,不能跑");
}
@Override
public void stop() {
System.out.println("【开门状态】已经停止,无需再次停止");
}
}
/**
* 具体状态:关门状态
*/
class CloseState implements ElevatorState {
private final ElevatorContext context;
public CloseState(ElevatorContext context) {
this.context = context;
}
@Override
public void open() {
System.out.println("【关门状态】执行开门,切换开门状态");
context.setState(new OpenState(context));
}
@Override
public void close() {
System.out.println("【关门状态】门已经关闭,无需重复关门");
}
@Override
public void run() {
System.out.println("【关门状态】电梯开始运行,切换运行状态");
context.setState(new RunState(context));
}
@Override
public void stop() {
System.out.println("【关门状态】本来就是静止,无操作");
}
}
/**
* 具体状态:运行状态
*/
class RunState implements ElevatorState {
private final ElevatorContext context;
public RunState(ElevatorContext context) {
this.context = context;
}
@Override
public void open() {
System.out.println("【运行状态】运行中禁止开门!");
}
@Override
public void close() {
System.out.println("【运行状态】门已经关闭");
}
@Override
public void run() {
System.out.println("【运行状态】电梯正在运行中");
}
@Override
public void stop() {
System.out.println("【运行状态】电梯停止,切换停止状态");
context.setState(new StopState(context));
}
}
/**
* 具体状态:停止状态
*/
class StopState implements ElevatorState {
private final ElevatorContext context;
public StopState(ElevatorContext context) {
this.context = context;
}
@Override
public void open() {
System.out.println("【停止状态】打开电梯门,切换开门状态");
context.setState(new OpenState(context));
}
@Override
public void close() {
System.out.println("【停止状态】执行关门,切换关门状态");
context.setState(new CloseState(context));
}
@Override
public void run() {
System.out.println("【停止状态】电梯开始运行,切换运行状态");
context.setState(new RunState(context));
}
@Override
public void stop() {
System.out.println("【停止状态】电梯已经停止");
}
}
// 测试客户端
class StateDemoMain {
public static void main(String[] args) {
// 初始状态:停止
ElevatorContext elevator = new ElevatorContext(new StopState(null));
System.out.println("===== 1.停止电梯开门 =====");
elevator.open();
System.out.println("\n===== 2.开门状态尝试运行 =====");
elevator.run();
System.out.println("\n=====3.关门,然后运行 =====");
elevator.close();
elevator.run();
System.out.println("\n=====4.运行中尝试开门 =====");
elevator.open();
System.out.println("\n=====5.运行中停止 =====");
elevator.stop();
}
}
输出结果
===== 1.停止电梯开门 =====
【停止状态】打开电梯门,切换开门状态
===== 2.开门状态尝试运行 =====
【开门状态】禁止运行!门还开着,不能跑
=====3.关门,然后运行 =====
【开门状态】执行关门,切换到关门状态
【关门状态】电梯开始运行,切换运行状态
=====4.运行中尝试开门 =====
【运行状态】运行中禁止开门!
=====5.运行中停止 =====
【运行状态】电梯停止,切换停止状态
优缺点总结
✅ 优点
消除大量 if‑else,每个状态逻辑独立,符合开闭原则;新增状态只需要新增状态类,不用修改旧代码
状态逻辑内聚在状态类,状态流转清晰
❌ 缺点
状态数量多的时候,类会膨胀;
状态之间互相持有上下文,耦合;
对比策略模式
状态模式:状态内部会主动切换下一个状态,行为随状态改变;状态之间有流转关系
策略模式:策略之间互不感知,策略由外部传入切换,没有内部自动流转
生产小优化:状态对象可以做成单例,不需要每次 new,减少对象创建开销。
本文原创作者:易君召,详见:https://www.yijunzhao.cc/about,转载请注明出处。
原文链接
欢迎访问