状态模式

状态模式(State)允许一个对象在其内部状态改变的时候改变它的行为,对象看起来似乎修改了它的类。

状态模式定义一个对象,这个对象可以通过管理其状态从而使得应用程序作出相应的变化。状态模式是一个非常常用的设计模式,它主要有两个角色组成:
(1)环境类:拥有一个状态成员,可以修改其状态并作出相应反应。
(2)状态类:表示一种状态,包含其相应的处理方法

 

例子:

比如小霸王游戏机中的射击游戏,就可能同时有好几个状态比如 跳跃,移动,射击,蹲下 等,如果对这些动作一个个进行处理判断,需要多个if-else不优雅不说 ,而且在遇到有组合动作的时候,实现就会变的更为复杂,这里可以使用状态模式来实现。

状态模式的思路是:首先创建一个状态对象或者数组,内部保存状态变量,然后内部封装好每种动作对应的状态,然后状态对象返回一个接口对象,它可以对内部的状态修改或者调用。

const SuperMarry = (function() {    
  let _currentState = [],        // 状态数组
      states = {
        jump() {console.log('跳跃!')},
        move() {console.log('移动!')},
        shoot() {console.log('射击!')},
        squat() {console.log('蹲下!')}
      }
  
  const Action = {
    changeState(arr) {  // 更改当前动作
      _currentState = arr
      return this
    },
    goes() {
      console.log('触发动作')
      _currentState.forEach(T => states[T] && states[T]())
      return this
    }
  }
  
  return {
    change: Action.changeState,
    go: Action.goes
  }
})()

SuperMarry
    .change(['jump', 'shoot'])
    .go()                    // 触发动作  跳跃!  射击!
    .go()                    // 触发动作  跳跃!  射击!
    .change(['squat'])
    .go()                    // 触发动作  蹲下!
这里可以使用ES6的class优化一下:

class SuperMarry {
  constructor() {
    this._currentState = []
    this.states = {
      jump() {console.log('跳跃!')},
      move() {console.log('移动!')},
      shoot() {console.log('射击!')},
      squat() {console.log('蹲下!')}
    }
  }
  
  change(arr) {  // 更改当前动作
    this._currentState = arr
    return this
  }
  
  go() {
    console.log('触发动作')
    this._currentState.forEach(T => this.states[T] && this.states[T]())
    return this
  }
}

new SuperMarry()
    .change(['jump', 'shoot'])
    .go()                    // 触发动作  跳跃!  射击!
    .go()                    // 触发动作  跳跃!  射击!
    .change(['squat'])
    .go()                    // 触发动作  蹲下!

 

状态模式和策略模式很像,它们都封装了一系列的算法或行为,它们都有一个上下文对象来把请求委托给封装类(策略类、状态机),但它们的意图不同:
 1.策略类的各个属性之间是平等平行的,它们之间没有任何联系
 2.状态机中的各个状态之间存在相互切换,且是被规定好了的。

posted @ 2019-06-23 23:15  哒哒呵~  阅读(159)  评论(0编辑  收藏  举报