State状态模式

状态模式的核心是将状态抽象为类,然后将状态的改变包含在类中,这样就避免了在client中写出大量的if...else的判断。同时符合了设计原则中的开闭原则。状态模式往往应用的场景是模式非常复杂的场景,比如状态之间的转换非常繁杂。状态模式的升级实际就是状态机,我们在之后会进行更详细的讨论。

状态模式的类图如下:


State状态模式_第1张图片
state pattern

context为上下文,实际可以理解为一个封装,封装了状态,这样就状态就对外不可见。同时状态类可以改变context上下文的状态,从而改变其行为。而状态之间的转换关系也被封装在了状态对象内部。

我们以设计模式之禅中所举的电梯的例子来进行介绍:
对于电梯来讲,具有open,close,run,stop这几个动作,而对于状态来讲,有OPENING_STATE, CLOSING_STATE, RUNNING_STATE, STOPPING_STATE这几个状态,状态之间的装换关系满足一下的表格:

open close run stop
OPENING_STATE ✔️
CLOSING_STATE ✔️ ✔️ ✔️
RUNNING_STATE ✔️
STOPPING_STATE ✔️ ✔️

代码如下:

public class Context {
    //定义出所有的电梯状态
    public final static OpenningState openningState = new OpenningState();
    public final static ClosingState closeingState = new ClosingState();
    public final static RunningState runningState = new RunningState();
    public final static StoppingState stoppingState = new StoppingState();
    //定一个当前电梯状态
    private LiftState liftState;
    public LiftState getLiftState() {
        return liftState;
    }
    public void setLiftState(LiftState liftState) {
        this.liftState = liftState;
        //把当前的环境通知到各个实现类中
        this.liftState.setContext(this);
    }

    public void open(){
        this.liftState.open();
    }
    public void close(){
        this.liftState.close();
    }
    public void run(){
        this.liftState.run();
    }
    public void stop(){
        this.liftState.stop();
    }
}

public abstract class LiftState {

    protected Context context;

    public Context getContext() {
        return context;
    }

    public void setContext(Context context) {
        this.context = context;
    }

    public abstract void open();

    public abstract void close();

    public abstract void run();

    public abstract void stop();
}

public class ClosingState extends LiftState {

    @Override
    public void close() {
        System.out.println("电梯门关闭...");
    }

    @Override
    public void open() {
        super.context.setLiftState(Context.openningState); //置为门敞状态
        super.context.getLiftState().open();
    }

    @Override
    public void run() {
        super.context.setLiftState(Context.runningState); //设置为运行状态;
        super.context.getLiftState().run();
    }

    @Override
    public void stop() {
        super.context.setLiftState(Context.stoppingState); //设置为停止状态;
        super.context.getLiftState().stop();
    }

}

public class OpenningState extends LiftState {

    @Override
    public void open() {
        System.out.println("电梯门开启...");
    }

    @Override
    public void close() {
        //状态修改
        super.context.setLiftState(Context.openningState);
        //动作委托为CloseState来执行
        super.context.getLiftState().close();
    }

    @Override
    public void run() {
    }

    @Override
    public void stop() {
    }
}

public class RunningState extends LiftState {

    @Override
    public void open() {

    }

    @Override
    public void close() {

    }

    @Override
    public void run() {
        System.out.println("电梯上下跑...");
    }

    @Override
    public void stop() {
        super.context.setLiftState(Context.stoppingState); //环境设置为停止状态;
        super.context.getLiftState().stop();
    }
}

public class StoppingState extends LiftState {

    @Override
    public void open() {
        super.context.setLiftState(Context.openningState);
        super.context.getLiftState().open();
    }

    @Override
    public void close() {

    }

    @Override
    public void run() {
        super.context.setLiftState(Context.runningState);
        super.context.getLiftState().run();
    }

    @Override
    public void stop() {
        System.out.println("电梯停止了...");
    }
}

public class Client {
    public static void main(String[] args) {
        Context context = new Context();
        context.setLiftState(new ClosingState());
        context.open();
        context.close();
        context.run();
        context.stop();
    }
}

你可能感兴趣的:(State状态模式)