状态模式

状态模式,个人认为通过将对象行为包装在不同状态对象里面,通过控制状态的变化来实现行为的差异。关于状态模式的使用场景,如果一个对象在不同状态(至少3个状态)下有不同行为,而且还有增加状态的趋势,可以考虑使用状态模式。拿电梯(来源于Java 设计模式——状态模式)来说,众所周知,电梯至少有四种状态: 开门状态,关门状态,运行状态,停止状态。

下面用一张表将状态和对应的动作列出来:        

 

对应的状态图:

为了有所区别,每个状态之间的联系是不一样的,如Closed状态和其他状态之间用虚线,而open状态和closed状态之前使用实线,可以看出,状态图和上面的表格是一致的。 下面再看看代码实现:

public interface IElevator {

    void open();
    void close();
    void run();
    void stop();
}
 1 public class Elevator implements IElevator {
 2 
 3     @Override
 4     public void open() {
 5         System.out.println("open the elevator");
 6     }
 7 
 8     @Override
 9     public void close() {
10         System.out.println("close the elevator");
11     }
12 
13     @Override
14     public void run() {
15         System.out.println("run the elevator");
16     }
17 
18     @Override
19     public void stop() {
20         System.out.println("stop the elevator");
21     }
22 }
public class Context {
    /*package*/ final State openState = new OpenState(this);
    /*package*/ final State closedState = new ClosedState(this);
    /*package*/ final State runningState = new RunningState(this);
    /*package*/ final State stoppedState = new StoppedState(this);

    /*package*/ final IElevator elevator;

    private State state;

    public Context(IElevator elevator) {
        this.elevator = elevator;
        this.state = openState;
    }

    public IElevator getElevator() {
        return elevator;
    }

    public void setState(State state) {
        this.state = state;
    }

    public void open() {
        state.open();
    }

    public void close() {
        state.close();
    }

    public void run() {
        state.run();
    }

    public void stop() {
        state.stop();
    }

    public static void main(String[] param) {
        Context context = new Context(new Elevator());
        context.close();
        context.run();
        context.open();
    }

}
public abstract class State implements IElevator {

    protected final Context context;

    public State(Context context) {
        this.context = context;
    }

    protected void log(String state, String action) {
        System.out.println("Elevator can't take action " + action + " in state " + state);
    }
}
public class OpenState extends State {

    public OpenState(Context context) {
        super(context);
    }

    @Override
    public void open() {
        log("open", "open");
    }

    @Override
    public void close() {
        context.getElevator().close();
        context.setState(context.closedState);
    }

    @Override
    public void run() {
        log("open", "run");
    }

    @Override
    public void stop() {
        log("open", "stop");
    }
}
public class ClosedState extends State {

    public ClosedState(Context context) {
        super(context);
    }

    @Override
    public void open() {
        context.getElevator().open();
        context.setState(context.openState);
    }

    @Override
    public void close() {
        log("closed", "close");
    }

    @Override
    public void run() {
        context.getElevator().run();
        context.setState(context.runningState);
    }

    @Override
    public void stop() {
        context.getElevator().stop();
        context.setState(context.stoppedState);
    }
}
public class RunningState extends State {

    public RunningState(Context context) {
        super(context);
    }

    @Override
    public void open() {
        log("running", "open");
    }

    @Override
    public void close() {
        log("running", "close");
    }

    @Override
    public void run() {
        log("running", "run");
    }

    @Override
    public void stop() {
        context.getElevator().stop();
    }
}
public class StoppedState extends State {

    public StoppedState(Context context) {
        super(context);
    }

    @Override
    public void open() {
        context.getElevator().open();
        context.setState(context.openState);
    }

    @Override
    public void close() {
        log("stopped", "close");
    }

    @Override
    public void run() {
        context.getElevator().run();
        context.setState(context.runningState);
    }

    @Override
    public void stop() {
        log("stopped", "stop");
    }
}

代码和简单,类图如下:

现在问题来了,新闻上经常报告电梯出事,上级要求每个电梯添加急救按钮,用户在紧急情况下可以按下此按钮逃生。想想看,如果之前没有使用状态模式,拿到这个需求程序员是不是有想死的冲动 , 而状态模式能很好解决这个需求只需要添加urgent动作就可以了。

如果各位还不过瘾,我想再拿个打电话的小例子,状态图如下:

如果手机新增一个urgent功能:

具体代码我就不展示了,具体代码可以参见: https://github.com/breakJeff/designPattern,如果发现问题,请及时留言。

原文地址:https://www.cnblogs.com/budoudou/p/6772779.html