设计模式-状态模式(State Pattern)

状态模式

定义
当一个对象内在状态改变时允许其改变行为,这个对象看起来像改变了其类。

类型
行为型。

UML类图
在这里插入图片描述

角色

  • 环境(Context)角色:环境角色含有状态角色的对象,并且可以处理一些请求,这些请求最终产生的响应会与状态相关。
  • 状态(State)角色:状态角色定义了每一个状态的行为接口,这些行为将会在Context中得以使用。
  • 具体状态(ConcreteState)角色:实现了相关行为的具体状态类。

例子
我们看课程视频时,可以播放、加速、暂停视频和停止视频(退出了观看课程视频界面)。

  • 当课程视频处于播放状态时,课程视频可以正常播放、加速、暂停、停止。
  • 当课程视频处于加速状态时,课程视频可以正常播放、加速、暂停、停止。
  • 当课程视频处于暂停状态时,课程视频可以正常播放、加速、暂停、停止。
  • 当课程视频处于停止状态时,课程视频可以正常播放、停止,而不能正常加速、暂停。

不用纠结这些规则,只是为了说明当一个对象内在状态改变时允许其改变行为

CourseVideoContext类(环境角色),含有状态角色的对象courseVideoState

package com.kaven.design.pattern.behavioral.state;

public class CourseVideoContext {

    private CourseVideoState courseVideoState;
    public final static PlayState PLAY_STATE = new PlayState();
    public final static SpeedState SPEED_STATE = new SpeedState();
    public final static PauseState PAUSE_STATE = new PauseState();
    public final static StopState STOP_STATE = new StopState();

    public CourseVideoState getCourseVideoState() {
        return courseVideoState;
    }

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

    public void play(){
        this.courseVideoState.play();
    }
    public void speed(){
        this.courseVideoState.speed();
    }
    public void pause(){
        this.courseVideoState.pause();
    }
    public void stop(){
        this.courseVideoState.stop();
    }
}

CourseVideoState类(状态角色),定义了每一个状态的行为接口,这些行为将会在Context中得以使用,从CourseVideoContext类代码也可以看出来。

package com.kaven.design.pattern.behavioral.state;

public abstract class CourseVideoState {
    protected CourseVideoContext courseVideoContext;

    public void setCourseVideoContext(CourseVideoContext courseVideoContext) {
        this.courseVideoContext = courseVideoContext;
    }

    public abstract void play();
    public abstract void speed();
    public abstract void pause();
    public abstract void stop();
}

PlayState类(具体状态角色),播放状态类,继承了CourseVideoState类,实现了对应的行为(根据上面说的规则)。

package com.kaven.design.pattern.behavioral.state;

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

    public void speed() {
        super.courseVideoContext.setCourseVideoState(CourseVideoContext.SPEED_STATE);
    }

    public void pause() {
        super.courseVideoContext.setCourseVideoState(CourseVideoContext.PAUSE_STATE);
    }

    public void stop() {
        super.courseVideoContext.setCourseVideoState(CourseVideoContext.STOP_STATE);
    }
}

SpeedState类(具体状态角色),加速状态类,继承了CourseVideoState类,实现了对应的行为(根据上面说的规则)。

package com.kaven.design.pattern.behavioral.state;

public class SpeedState extends CourseVideoState {
    public void play() {
        super.courseVideoContext.setCourseVideoState(CourseVideoContext.PLAY_STATE);
    }

    public void speed() {
        System.out.println("快进播放课程视频状态");
    }

    public void pause() {
        super.courseVideoContext.setCourseVideoState(CourseVideoContext.PAUSE_STATE);
    }

    public void stop() {
        super.courseVideoContext.setCourseVideoState(CourseVideoContext.STOP_STATE);
    }
}

PauseState类(具体状态角色),暂停状态类,继承了CourseVideoState类,实现了对应的行为(根据上面说的规则)。

package com.kaven.design.pattern.behavioral.state;

public class PauseState extends CourseVideoState {
    public void play() {
        super.courseVideoContext.setCourseVideoState(CourseVideoContext.PLAY_STATE);
    }

    public void speed() {
        super.courseVideoContext.setCourseVideoState(CourseVideoContext.SPEED_STATE);
    }

    public void pause() {
        System.out.println("暂停播放课程视频状态");
    }

    public void stop() {
        super.courseVideoContext.setCourseVideoState(CourseVideoContext.STOP_STATE);
    }
}

StopState类(具体状态角色),停止状态类,继承了CourseVideoState类,实现了对应的行为(根据上面说的规则)。

package com.kaven.design.pattern.behavioral.state;

public class StopState extends CourseVideoState {
    public void play() {
        super.courseVideoContext.setCourseVideoState(CourseVideoContext.PLAY_STATE);
    }

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

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

    public void stop() {
        System.out.println("停止播放课程视频状态");
    }
}

应用层代码:

package com.kaven.design.pattern.behavioral.state;

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());

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

输出:

当前状态:PlayState
当前状态:PauseState
当前状态:SpeedState
当前状态:StopState
ERROR 停止状态不能快进
当前状态:StopState

好好去理清楚这些代码的逻辑。
这里便完成了一个简单的状态模式的例子。

适用场景

  • 行为随状态改变而改变的场景。
  • 条件、分支语句的代替者。

优点

  • 封装了转换规则。
  • 将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。
  • 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。

缺点

  • 状态模式的使用必然会增加系统类和对象的个数。
  • 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱。
  • 状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码。

如果有说错的地方,请大家不吝赐教(记得留言哦~~~~)。

发布了288 篇原创文章 · 获赞 325 · 访问量 65万+

猜你喜欢

转载自blog.csdn.net/qq_37960603/article/details/104128650
今日推荐