美文网首页
状态模式

状态模式

作者: yongningfu | 来源:发表于2017-04-02 14:37 被阅读0次

    状态模式

    工作中,常常使用到状态机,如何才能把一个流程确定的状态机代码编写好,恰恰是状态模式要解决的问题。
    假设目前有一个场景,一个按钮有A B C三种状态,状态切换的流程为 A -> B -> C -> A...
    按钮在不同的状态下面,按钮执行不同的点击动作,如何去编写者一块代码?
    一般的编写思路为

    
    // html <button id="button">click</button>
    var state = {A: 1, B: 2, C: 3};
    var currentState = state.A; //default
    var button = document.getElementById("button");
    button.onclick = function() {
      if (currentState === state.A) {
          console.log('operating in state A');
          currentState = state.B;
      } else if (currentState === state.B) {
          console.log('operating in state B');
          currentState = state.C;
      } else if (currentState === state.C) {
          console.log('operating in state C');
          currentState = state.A;
      } else {
          throw new Error("can not find the state");
      }
    }
    

    上面的写法有什么问题吗?当然是有的,多个状态全部用if else判断,如果新增状态的话,是不是要修改这个onclick函数,而且如果在不同的状态下,做的逻辑比较复杂的话,是不是onclick函数会显得臃肿许多。
    有没有更好的办法呢?

    1. 使用状态模式,状态模式要解决的问题是,在当前的状态下面,就直接做这个动作,而不是判断是否处于这个状态下面,去做这个动作,类似于多态,不管你当前是啥,反正我直接调用你这个动作执行的方法就行了,
    2. 在状态模式使用的过程中,我们一般使用委托,把当前需要做的动作,直接委托到当前这个状态的对象的动作中来,无需判断当前是处于哪个状态,所以状态对象提供的动作接口必须是一致的

    状态模式改进版

    // 为了向上提供一致的接口,每个状态执行的动作函数名称必须一致
    var FSM = {
        A: {
            //我只是关心A状态下面 会做什么
            handler: function() {
                console.log('operating in state A');
                currentState = FSM.B;
            }
        },
        B: {
            handler: function() {
                console.log('operating in state B');
                currentState = FSM.C;
            }
        },
        C: {
            handler: function() {
                console.log('operating in state C');
                currentState = FSM.A;
            }
        }
    }
    
    var currentState = FSM.A; //default
    var button = document.getElementById("button");
    button.onclick = function() {
        currentState.handler.call(this); 
        //把当前的onclick委托给 现在状态的handler
        //这里我不关心当前这个状态是什么,我只是关心当前这个状态会发生什么,所以去除了if else
    }
    

    完整代码:

    <!DOCTYPE html>
    <html>
      <head></head>
    <body>
    <button id="button">click</button>
    <script type="text/javascript">
    
    // 为了向上提供一致的接口,每个状态执行的动作函数名称必须一致
    var FSM = {
        A: {
            //我只是关心A状态下面 会做什么
            handler: function() {
                console.log('operating in state A');
                currentState = FSM.B;
            }
        },
        B: {
            handler: function() {
                console.log('operating in state B');
                currentState = FSM.C;
            }
        },
        C: {
            handler: function() {
                console.log('operating in state C');
                currentState = FSM.A;
            }
        }
    }
    
    var currentState = FSM.A; //default
    var button = document.getElementById("button");
    button.onclick = function() {
        currentState.handler.call(this);  
        //用call的目的是 如果状态里面想要当前对象的话,可以把当前对象 this传递过去
        //把当前的onclick委托给 现在状态的handler
        //这里我不关心当前这个状态是什么,我只是关心当前这个状态会发生什么,所以去除了if else
    }
        </script>
      </body>
    
    </html>
    
    
    

    相关文章

      网友评论

          本文标题:状态模式

          本文链接:https://www.haomeiwen.com/subject/nodgottx.html