• 状态模式


    状态模式,个人认为通过将对象行为包装在不同状态对象里面,通过控制状态的变化来实现行为的差异。关于状态模式的使用场景,如果一个对象在不同状态(至少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,如果发现问题,请及时留言。

  • 相关阅读:
    hdu 2044 一只小蜜蜂
    HDU 2041 超级楼梯
    卡特兰数
    hdu 1267 下沙的沙子有几粒?(二维递推题)
    大数加法、乘法
    学习时仪式感太强是不是不太好
    php记日志
    cygwin安装apt-cyg
    存储过程死循环之后的清理
    linux的计划任务crontab
  • 原文地址:https://www.cnblogs.com/budoudou/p/6772779.html
Copyright © 2020-2023  润新知