小易说IT 小易说IT

Java 状态模式 (State)示例代码

状态模式:允许对象在内部状态改变时改变它的行为,对象看起来好像修改了它的类。核心:把每个状态封装成独立类,上下文对象持有状态引用,状态切换委托状态类处理

适用场景:对象行为依赖状态,大量 if‑else/switch 判断状态分支。

UML 角色

  1. State(抽象状态):定义各状态公共行为接口

  2. ConcreteState(具体状态):实现对应状态下的业务逻辑

  3. 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.运行中停止 =====
【运行状态】电梯停止,切换停止状态

优缺点总结

优点

  1. 消除大量 if‑else,每个状态逻辑独立,符合开闭原则;新增状态只需要新增状态类,不用修改旧代码

  2. 状态逻辑内聚在状态类,状态流转清晰

缺点

  1. 状态数量多的时候,类会膨胀;

  2. 状态之间互相持有上下文,耦合;

对比策略模式

  • 状态模式:状态内部会主动切换下一个状态,行为随状态改变;状态之间有流转关系

  • 策略模式:策略之间互不感知,策略由外部传入切换,没有内部自动流转

生产小优化:状态对象可以做成单例,不需要每次 new,减少对象创建开销。


本文原创作者:易君召,详见:https://www.yijunzhao.cc/about,转载请注明出处。

原文链接 https://yijunzhao.cc/archives/java-state-pattern-example-code

欢迎访问 https://www.yijunzhao.cc/

https://www.yijunzhao.cc/