课程大纲 / Lesson 13
State 行为型

State · 状态

允许对象在内部状态改变时改变它的行为,看起来好像修改了其类。

01

理解状态模式:将状态行为封装到独立状态类中,避免大量条件分支

02

掌握 State(抽象状态)与 ConcreteState(具体状态)的结构,以及状态切换机制

03

理解状态模式与策略模式的区别:状态模式状态决定行为,策略模式客户决定算法

04

了解状态模式在播放器、订单系统、TCP 连接、导航等场景中的应用

核心概念
状态决定行为状态类封装状态切换消除条件分支
classDiagram class state { <<interface>> +clicklock(player player) +clickplay(player player) +clicknext(player player) } class lockedstate { <<stateless>> +clicklock(player player) +clickplay(player player) +clicknext(player player) } class readystate { <<stateless>> +clicklock(player player) +clickplay(player player) +clicknext(player player) } class playingstate { <<stateless>> +clicklock(player player) +clickplay(player player) +clicknext(player player) } class player { -state state +changestate(state state) +clicklock() +clickplay() +clicknext() } state <|.. lockedstate state <|.. readystate state <|.. playingstate player *-- state state --> player

player 将行为委托给当前 state,状态对象负责行为和转换规则

点击 Run 运行状态机...
/** 抽象状态接口:所有具体状态实现此接口 */
public interface State {
    void clickLock(Player player);
    void clickPlay(Player player);
    void clickNext(Player player);
}
/** 锁定状态:只能响应 clickLock 切到 ReadyState */
public class LockedState implements State {

    public void clickLock(Player player) {
        player.changeState(new ReadyState());
        System.out.println("Locked → Ready");
    }

    public void clickPlay(Player player) {
        System.out.println("Locked: do nothing");
    }

    public void clickNext(Player player) {
        System.out.println("Locked: do nothing");
    }
}
/** 就绪状态:clickPlay → PlayingState,clickLock → LockedState */
public class ReadyState implements State {

    public void clickLock(Player player) {
        player.changeState(new LockedState());
        System.out.println("Ready → Locked");
    }

    public void clickPlay(Player player) {
        player.changeState(new PlayingState());
        System.out.println("Ready → Playing");
    }

    public void clickNext(Player player) {
        System.out.println("Ready: do nothing");
    }
}
/** 播放状态:clickPlay/clickNext → 就绪,clickLock → 锁定 */
public class PlayingState implements State {

    public void clickLock(Player player) {
        player.changeState(new LockedState());
        System.out.println("Playing → Locked");
    }

    public void clickPlay(Player player) {
        player.changeState(new ReadyState());
        System.out.println("Playing → Ready (paused)");
    }

    public void clickNext(Player player) {
        System.out.println("Playing: next track");
    }
}
/** 播放器:持有当前状态,将操作委托给当前状态对象 */
public class Player {
    private State state;

    public Player() {
        state = new LockedState();
    }

    public void changeState(State s) { state = s; }

    public void clickLock()  { state.clickLock(this); }
    public void clickPlay() { state.clickPlay(this); }
    public void clickNext() { state.clickNext(this); }
}
public class Demo {
    public static void main(String[] args) {
        Player player = new Player();
        player.clickLock();   // Locked → Ready
        player.clickPlay();  // Ready → Playing
        player.clickNext(); // Playing: next track
        player.clickPlay();  // Playing → Ready
    }
}
◈

状态决定行为,消除条件分支

Player.clickPlay() 本身不包含任何 if/else;行为完全由当前 State 对象决定,每个状态类只实现自己该有的行为。

◈

状态转换逻辑在状态类内部

ReadyState.clickPlay() 决定切换到 PlayingState;LockedState.clickLock() 决定切换到 ReadyState;状态转换逻辑集中在状态类而非 Player。

◈

状态模式 vs. 策略模式

状态模式:状态对象决定行为,且状态间相互感知(LockedState 知道如何切 ReadyState);策略模式:客户选择算法,策略之间无关联。

◈

典型应用场景

媒体播放器(Locked/Ready/Playing)、订单系统(待支付/已支付/已取消)、TCP 连接(LISTEN/SYN_SENT/ESTABLISHED)、导航状态机、游戏角色状态。