設計模式之狀態模式

定義

允許一個對象在其內部狀態改變時,改變它的行爲。

類型

行爲型

適用場景

①、一個對象存在多個狀態(不同狀態下行爲不同),且狀態可相互轉換。

優缺點

優點:
①、將不同的狀態隔離。
②、把各種狀態的轉換邏輯,分佈到State的子類中,減少相互間依賴。
③、增加新的狀態非常簡單。

缺點:
①、狀態多的業務場景導致類數目增加,系統變複雜。

代碼實現

案例:博主經常在B站看番,有時候會快進、有時候會暫停、看完了就關閉當前視屏了。可以看到,視屏是有很多狀態的:開始播放、暫停播放、快進播放、停止播放。
首先創建一個視頻的狀態類

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

CourseVideoContext這個類是視頻的上下文。裏面是做視頻狀態的切換以及狀態的管理。

public class CourseVideoContext {

    private CourseVideoState courseVideoState;

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

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

this.courseVideoState.setCourseVideoContext(this)這個方法,用來刷新最新的上下文。
上面還聲明瞭四種狀態的常量,接下來一一創建。
創建開始播放狀態CourseVideoState的實現類。

public class PlayState extends CourseVideoState {

    @Override
    public void play() {
        System.out.println("狀態:播放視頻");
    }

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

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

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

視頻開始播放,都能隨時切換到其他的三種狀態。
創建暫停播放狀態CourseVideoState的實現類。

public class PauseState extends CourseVideoState {

    @Override
    public void play() {
        super.courseVideoContext.setCourseVideoState(CourseVideoContext.PLAY_STATE);
    }

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

    @Override
    public void pause() {
        System.out.println("狀態:暫停視頻");
    }

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

暫停視屏的時候,也是能夠切換到其他三種狀態的。
創建快進播放狀態CourseVideoState的實現類。

public class SpeedState extends CourseVideoState {

    @Override
    public void play() {
        super.courseVideoContext.setCourseVideoState(CourseVideoContext.PLAY_STATE);
    }

    @Override
    public void speed() {
        System.out.println("狀態:快進視頻");
    }

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

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

快進和暫停相似。
創建停止播放狀態CourseVideoState的實現類。

public class StopState extends CourseVideoState {

    @Override
    public void play() {
        super.courseVideoContext.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("狀態:停止視頻播放");
    }
}

按照常理,當視頻停止播放了,是沒有辦法切換到快進和暫停狀態的,所以這裏直接輸出錯誤信息。
編寫測試類

    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());
        // 停止播放的狀態下切換SpeedState或者PauseState狀態,會報錯
        courseVideoContext.pause();
        System.out.println("當前狀態:" + courseVideoContext.getCourseVideoState().getClass().getSimpleName());
    }
}

輸出結果:

相關源碼

1. JSF中的Lifecycle類

參考鏈接
https://coding.imooc.com/learn/list/270.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章