20.状态模式

2018-08-14  本文已影响0人  0x70e8

[TOC]

状态模式

状态模式是使用类来表示一种状态,和通常使用类来表示一个实体不同,这种应用场景下表示的是一个非实体。

一般而言,一个实体的状态能够影响实体上的行为,如一个人睡着了就不能工作,一个实体的行为反过来又会影响他的状态,工作了就从睡着变成醒来的状态。

类是有行为的数据,在类里面定义状态可能发生的行为(方法),然后在行为(方法)内判断行为能否发生,并决定是否会影响当前的状态。

此模式能将代码逻辑从大量的if-else中解脱出来,分散到多个类中。

示例

如电梯的上下开关和其状态的关系。

不使用state模式的伪代码

// 电梯的状态 开着门open、关着门close、运行中running、静止stop
// 传入电梯动作(开门open、关门close、运行run、停止stop)
void act(action){
    if(action is run){
        //判断当前状态
        if(curState is run){
            
        }else if(curState is stop){
            
        }else if(cur is close){
            
        }else{
            // open
        }
        
    }else if(action is stop){
        //判断当前状态
        if(curState is run){
            
        }else if(curState is stop){
            
        }else if(cur is close){
            
        }else{
            // open
        }
    }else if(action is open the door){
        //判断当前状态
        if(curState is run){
            
        }else if(curState is stop){
            
        }else if(cur is close){
            
        }else{
            // open
        }
    }else{//action is close the door
        //判断当前状态
        if(curState is run){
            
        }else if(curState is stop){
            
        }else if(cur is close){
            
        }else{
            // open
        }
    }
}

发现会有大量的if-else语句,且在内部还需要针对action来修改电梯的状态,逻辑很复杂,并且当状态或者行为有新增的时候,将是一场噩梦。

使用state模式

使用类表示状态,实际上是封装状态和行为:

public abstract class LiftState {

    private StateEnum state;

    public abstract void run();

    public abstract void stop();

    public abstract void close();

    public abstract void open();

    /**
     * @return the state
     */
    public StateEnum getState() {
        return state;
    }

    /**
     * @param state
     *            the state to set
     */
    public void setState(StateEnum state) {
        this.state = state;
    }
}
public enum StateEnum {
    RUN, STOP, OPEN, CLOSE;
}
public class LIftCloseState extends LiftState {
    public LIftCloseState() {
        this.setState(StateEnum.CLOSE);
    }

    @Override
    public void run() {
        System.out.println("run it!");
        this.setState(StateEnum.RUN);
    }

    @Override
    public void stop() {
        System.out.println("stop it");
        this.setState(StateEnum.STOP);
    }

    @Override
    public void close() {
        System.out.println("already closed ");
        this.setState(StateEnum.CLOSE);
    }

    @Override
    public void open() {
        System.out.println("open it");
        this.setState(StateEnum.OPEN);

    }

}

public class LIftOpenState extends LiftState {
    public LIftOpenState() {
        this.setState(StateEnum.OPEN);
    }

    @Override
    public void run() {
        System.out.println("cannot  run!");

    }

    @Override
    public void stop() {
        System.out.println("already stop");
        this.setState(StateEnum.STOP);
    }

    @Override
    public void close() {
        System.out.println("close it");
        this.setState(StateEnum.CLOSE);
    }

    @Override
    public void open() {
        System.out.println("already open");
        this.setState(StateEnum.OPEN);
    }

}

public class LIftRunState extends LiftState {
    public LIftRunState() {
        this.setState(StateEnum.RUN);
    }

    @Override
    public void run() {
        System.out.println("already run!");
        this.setState(StateEnum.RUN);
    }

    @Override
    public void stop() {
        System.out.println("stop it");
        this.setState(StateEnum.STOP);

    }

    @Override
    public void close() {
        System.out.println("already closed");
        this.setState(StateEnum.CLOSE);
    }

    @Override
    public void open() {
        System.out.println("can not open");

    }

}

public class LIftStopState extends LiftState {
    public LIftStopState() {
        this.setState(StateEnum.STOP);
    }

    @Override
    public void run() {
        System.out.println("start run!");
        this.setState(StateEnum.RUN);
    }

    @Override
    public void stop() {
        System.out.println("already stop");
        this.setState(StateEnum.STOP);
    }

    @Override
    public void close() {
        System.out.println("close the lift");
        this.setState(StateEnum.CLOSE);
    }

    @Override
    public void open() {
        System.out.println("open the lift");
        this.setState(StateEnum.OPEN);

    }

}

public class Client {

    public static void main(String[] args) {
        LiftState state = new LIftOpenState();
        state.close();
        state.run();
        state.stop();
        state.open();
        state.close();
        state.run();
        state.open();
        state.stop();

    }

}

可以发现,状态的判断分散到状态的类中去了,每个状态类维护其上可以发生的行为以及行为会改变的状态。没有了if-else语句,且此情况下,增加一个状态时只需要增加一个类,可能需要修改其他state的方法(影响状态的行为),但是维护起来比if-else方便很多。

缺点是会产生很多类。

上一篇下一篇

猜你喜欢

热点阅读