参考文献

状态模式

  • 允许对象在其内部状态发生变化时改变其行为

组件

  • 状态接口(State Interface):定义了表示各种状态的方法,具体状态类必须实现该接口.
  • 具体状态类(Concrete State Class):实现了状态接口的具体状态类,每个具体状态类负责处理特定的状态下的行为.
  • 上下文类(Context Class):维护一个对当前状态对象的引用,提供了用于切换状态和执行相应操作的方法.
    • 环境类状态切换方法(Transition Methods in Context Class):在上下文类中提供了用于切换状态的方法,允许客户端自行决定何时切换状态.
    • 共享状态(Shared State):多个上下文对象共享同一个状态对象的情况.这种情况下,可以将状态对象设计成可共享的,以减少对象的创建和内存占用.

实现方式

  • 定义状态接口(State Interface):创建一个表示状态的接口,其中包含了各种状态下的方法.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public abstract class CourseVideoState {
    protected CourseVideoContext mCourseVideoContext;

    public void setCourseVideoContext(CourseVideoContext courseVideoContext) {
    mCourseVideoContext = courseVideoContext;
    }

    public abstract void play();

    public abstract void speed();

    public abstract void pause();

    public abstract void stop();
    }
  • 创建具体状态类(Concrete State Class):实现状态接口的具体状态类,每个具体状态类负责处理特定状态下的行为.

    • 将状态切换方法添加到上下文类中(Optional):如果需要客户端能够主动切换状态,可以在上下文类中添加相应的方法.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    public class PauseState extends CourseVideoState {
    @Override
    public void play() {
    super.mCourseVideoContext.setCourseVideoState(CourseVideoContext.PLAY_STATE);

    }

    @Override
    public void speed() {
    super.mCourseVideoContext.setCourseVideoState(CourseVideoContext.SPEED_STATE);

    }

    @Override
    public void pause() {
    System.out.println("课程视频已暂停");
    }

    @Override
    public void stop() {
    super.mCourseVideoContext.setCourseVideoState(CourseVideoContext.STOP_STATE);

    }
    }

    public class PlayState extends CourseVideoState {
    @Override
    public void play() {
    System.out.println("正常播放课程视频状态");
    }

    @Override
    public void speed() {
    super.mCourseVideoContext.setCourseVideoState(CourseVideoContext.SPEED_STATE);
    }

    @Override
    public void pause() {
    super.mCourseVideoContext.setCourseVideoState(CourseVideoContext.PAUSE_STATE);

    }

    @Override
    public void stop() {
    super.mCourseVideoContext.setCourseVideoState(CourseVideoContext.STOP_STATE);

    }
    }

    public class SpeedState extends CourseVideoState {
    @Override
    public void play() {
    super.mCourseVideoContext.setCourseVideoState(CourseVideoContext.PLAY_STATE);

    }

    @Override
    public void speed() {
    System.out.println("课程视频正在加速");
    }

    @Override
    public void pause() {
    super.mCourseVideoContext.setCourseVideoState(CourseVideoContext.PAUSE_STATE);

    }

    @Override
    public void stop() {
    super.mCourseVideoContext.setCourseVideoState(CourseVideoContext.STOP_STATE);

    }
    }


    public class StopState extends CourseVideoState {
    @Override
    public void play() {
    super.mCourseVideoContext.setCourseVideoState(CourseVideoContext.PLAY_STATE);

    }

    @Override
    public void speed() {
    System.out.println("ERROR 停止状态不能快进!!");
    }

    @Override
    public void pause() {
    System.out.println("ERROR 停止状态不能暂停!!");

    }

    @Override
    public void stop() {
    System.out.println("课程视频停止播放");
    }
    }
  • 实现上下文类(Context Class):维护一个对当前状态对象的引用,并提供用于切换状态和执行相应操作的方法.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    public class CourseVideoContext {
    private CourseVideoState mCourseVideoState;
    public final static PlayState PLAY_STATE = new PlayState();
    public final static PauseState PAUSE_STATE = new PauseState();
    public final static SpeedState SPEED_STATE = new SpeedState();
    public final static StopState STOP_STATE = new StopState();

    public CourseVideoState getCourseVideoState() {
    return mCourseVideoState;
    }

    public void setCourseVideoState(CourseVideoState courseVideoState) {
    mCourseVideoState = courseVideoState;
    this.mCourseVideoState.setCourseVideoContext(this);
    }

    public void play() {
    this.mCourseVideoState.play();
    }

    public void pause() {
    this.mCourseVideoState.pause();

    }

    public void speed() {
    this.mCourseVideoState.speed();

    }

    public void stop() {
    this.mCourseVideoState.stop();

    }
    }
  • 在客户端代码中使用状态模式:创建上下文对象并调用不同状态下的方法,观察输出结果.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    public class Test {
    public static void main(String[] args) {
    CourseVideoContext courseVideoContext = new CourseVideoContext();
    courseVideoContext.setCourseVideoState(new PlayState());

    System.out.println("当前的状态:" + courseVideoContext.getCourseVideoState().getClass().getSimpleName());
    courseVideoContext.pause();

    System.out.println("当前的状态:" + courseVideoContext.getCourseVideoState().getClass().getSimpleName());
    courseVideoContext.speed();

    System.out.println("当前的状态:" + courseVideoContext.getCourseVideoState().getClass().getSimpleName());
    courseVideoContext.stop();
    System.out.println("当前的状态:" + courseVideoContext.getCourseVideoState().getClass().getSimpleName());

    }
    }

使用场景

  • 如果对象需要根据自身当前状态进行不同行为, 同时状态的数量非常多且与状态相关的代码会频繁变更的话, 可使用状态模式.
  • 如果某个类需要根据成员变量的当前值改变自身行为, 从而需要使用大量的条件语句时, 可使用该模式.
  • 当相似状态和基于条件的状态机转换中存在许多重复代码时, 可使用状态模式.