1. 程式人生 > 實用技巧 >P3817 小A的糖果

P3817 小A的糖果

一、狀態模式介紹

1、定義與型別

允許一個物件在其內部狀態改變時,改變它的行為
型別:行為型

2、適用場景

一個物件存在多個狀態(不同狀態下行為不同),且狀態可相互轉換

3、優點

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

4、缺點

狀態多的業務場景導致類數目增加,系統變複雜

5、相關設計模式

狀態模式和享元模式 有時候可以配合進行使用

二、程式碼示例

模擬場景:看視訊時,可以切換為播放狀態、暫停狀態、快進狀態、停止狀態

視訊狀態抽象類:

public abstract class VideoVideoState {
    // 與上下文 互相巢狀
    protected VideoStateContext videoStateContext;

    public void setVideoStateContext(VideoStateContext videoStateContext) {
        this.videoStateContext = videoStateContext;
    }

    public abstract void paly();

    public abstract void speed();

    public abstract void pause();

    public abstract void stop();
}

播放狀態類:

public class PlayState extends VideoVideoState {
    @Override
    public void paly() {
        System.out.println("正常播放課程視訊的狀態");
    }

    @Override
    public void speed() {
        System.out.println("快進了視訊");
        super.videoStateContext.setVideoVideoState(VideoStateContext.SPEED_STATE);
    }

    @Override
    public void pause() {
        System.out.println("暫停了視訊");
        super.videoStateContext.setVideoVideoState(VideoStateContext.PAUSE_STATE);
    }

    @Override
    public void stop() {
        System.out.println("停止了視訊");
        super.videoStateContext.setVideoVideoState(VideoStateContext.STOP_STATE);
    }
}

暫停狀態類:

public class PauseState extends VideoVideoState {
    @Override
    public void paly() {
        System.out.println("播放了視訊");
        super.videoStateContext.setVideoVideoState(VideoStateContext.PLAY_STATE);
    }

    @Override
    public void speed() {
        System.out.println("快進了視訊");
        super.videoStateContext.setVideoVideoState(VideoStateContext.SPEED_STATE);
    }

    @Override
    public void pause() {
        System.out.println("暫停播放課程視訊的狀態");
    }

    @Override
    public void stop() {
        System.out.println("停止了視訊");
        super.videoStateContext.setVideoVideoState(VideoStateContext.STOP_STATE);
    }
}

快進狀態類:

public class SpeedState extends VideoVideoState {
    @Override
    public void paly() {
        System.out.println("播放了視訊");
        super.videoStateContext.setVideoVideoState(VideoStateContext.PLAY_STATE);
    }

    @Override
    public void speed() {
        System.out.println("快進播放課程視訊的狀態");
    }

    @Override
    public void pause() {
        System.out.println("暫停了視訊");
        super.videoStateContext.setVideoVideoState(VideoStateContext.PAUSE_STATE);
    }

    @Override
    public void stop() {
        System.out.println("停止了視訊");
        super.videoStateContext.setVideoVideoState(VideoStateContext.STOP_STATE);
    }
}

停止狀態類:

public class StopState extends VideoVideoState {
    @Override
    public void paly() {
        System.out.println("播放了視訊");
        super.videoStateContext.setVideoVideoState(VideoStateContext.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 class VideoStateContext {
    // 與視訊狀態類 互相巢狀
    private VideoVideoState videoVideoState;
    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 VideoStateContext() {
        // 設定預設停止狀態
        this.videoVideoState = STOP_STATE;
        this.videoVideoState.setVideoStateContext(this);
    }

    public VideoVideoState getVideoVideoState() {
        return videoVideoState;
    }

    public void setVideoVideoState(VideoVideoState videoVideoState) {
        // 切換狀態
        this.videoVideoState = videoVideoState;
        this.videoVideoState.setVideoStateContext(this);
    }

    public void paly() {
        this.videoVideoState.paly();
    }

    public void speed() {
        this.videoVideoState.speed();
    }

    public void pause() {
        this.videoVideoState.pause();
    }

    public void stop() {
        this.videoVideoState.stop();
    }
}

測試類:

public class Test {
    public static void main(String[] args) {
        VideoStateContext videoStateContext = new VideoStateContext();

        videoStateContext.paly();

        System.out.println("當前狀態:" + videoStateContext.getVideoVideoState().getClass().getSimpleName());

        videoStateContext.pause();
        System.out.println("當前狀態:" + videoStateContext.getVideoVideoState().getClass().getSimpleName());

        videoStateContext.speed();
        System.out.println("當前狀態:" + videoStateContext.getVideoVideoState().getClass().getSimpleName());

        videoStateContext.stop();
        System.out.println("當前狀態:" + videoStateContext.getVideoVideoState().getClass().getSimpleName());

        videoStateContext.speed();
    }
}

輸出:
播放了視訊
當前狀態:PlayState
暫停了視訊
當前狀態:PauseState
快進了視訊
當前狀態:SpeedState
停止了視訊
當前狀態:StopState
ERROR 停止狀態不能快進!

類圖:

三、 原始碼示例

1、jsf中的LifeCycle