关于状态模式我所知道的

简介: 关于状态模式我所知道的

image.png


关键词:行为型 状态模式 StatePattern


解决什么问题?


状态机 State Machine:

一种数学模型,用于描述状态转换的逻辑。常用实现的方法:分支逻辑法、查表法、状态模式。

有三部分组成:状态(State)、事件(Event)、动作(Action)。

事件(转移条件)触发状态的转移及动作的执行。其中,动作不是必须的。


image.png

状态模式是状态机的一种实现方式。

实例对象内部状态发生改变,方法也发生改变。看上去就像换了个所属类一样。


应用场景


需要根据自身当前状态执行不同方法。

相似状态或者状态机里各个条件中有许多重复代码。将公用代码抽取到抽象基类中来减少重复。


具体实践


状态模式的关键是区分事物内部的状态,内部状态的改变影响事物的行为的改变。

简单举例:

灯亮,按开关,灯灭。

灯暗,按开关,灯亮。

同一个开关按钮,在不同的状态下,表现行为不一样。

// 非状态模式
class Light {
  constructor() {
    this.state = 'off';// 开关状态
    this.button = null;
  }
  init() {
    const btn = document.createElement('button');
    const _this = this;
    btn.innerText = '开关'; 
    this.button = document.body.appendChild(btn);
    this.button.onclick = () => {
      _this.btnPressed()
    }
  }
  btnPressed() {
    if (this.state === 'off') {
      console.log('开灯');
      this.state = 'on'
    } else if (this.state === 'on') {
      console.log('关灯');
      this.state = 'off'
    }
  }
}
const light = new Light()
light.init()


如果增加灯光类型,就需要在 btnPressed 方法中不断添加判断。这回造成 btnPressed 需要做的事情太多,也不符合程序设计的开闭原则(需要直接改动 light 类里面的代码)。


通过状态模式改进


使每种状态和它对应的行为之间的关系局部化,这些行为被分散和封装在各自对应的状态类之中,便于阅读和管理代码。

状态之间的切换都被分布在状态类内部,这使得我们无需编写过多的条件分支语言来控制状态之间的转换。

增加新状态也只需要增加一个新的状态类,然后改变状态类之间的切换规则就可以了。

// 将状态类全部抽离
class OffLightState {
  constructor(light) {
    this.light = light
  }
  btnPressed() {
    console.log('弱光')
    this.light.setState(this.light.weakLightState)
  }
}
class WeakLightState {
  constructor(light) {
    this.light = light
  }
  btnPressed() {
    console.log('强光')
    this.light.setState(this.light.strongLightState)
  }
}
class StrongLightState {
  constructor(light) {
    this.light = light
  }
  btnPressed() {
    console.log('关灯')
    this.light.setState(this.light.offLightState)
  }
}
// 上下文类 负责切换
class Light {
  constructor() {
    this.offLightState = new OffLightState(this)
    this.weakLightState = new WeakLightState(this)
    this.strongLightState = new StrongLightState(this)
    this.button = null
  }
  init() {
    const btn = document.createElement('button');
    const _this = this;
    btn.innerText = '开关';
    this.button = document.body.appendChild(btn);
    this.curState = this.offLightState;
    this.button.onclick = () => {
      _this.curState.btnPressed()
    }
  }
  setState(newState) {
    this.curState = newState
  }
  btnPressed(){
    throw new Error('btnPressed 必须被重写')
  }
}
const light = new Light()
light.init()

结构看上去与策略模式相似,不同点在于:

  • 状态之间是知道有其他状态存在的,且能触发从一个状态到另一个状态。
  • 策略则完全不知道其他策略的存在。

状态可被视为策略的扩展。两者都基于组合机制:通过将部分工作委派给 “帮手” 对象来改变其在不同情景下的行为。

参考资料

JS设计模式 状态模式

设计模式之美 状态模式

refactoringguru state

目录
相关文章
|
3月前
|
设计模式 算法
状态模式和策略模式有什么区别
状态模式和策略模式有什么区别
35 1
|
3月前
行为型 状态模式
行为型 状态模式
34 0
|
8月前
|
前端开发
状态模式
状态模式
35 0
|
设计模式 算法 Java
状态模式和策略模式的区别与联系
UML 状态模式是策略模式的孪生兄弟,是因为它们的UML图是一样的。但意图却完全不一样,策略模式是让用户指定更换的策略算法,而状态模式是状态在满足一定条件下的自动更换,用户无法指定状态,最多只能设置初始状态。
|
设计模式
我学会了,状态模式
状态模式属于行为型模式,这个类型的设计模式总结出了 类、对象之间的经典交互方式,将类、对象的行为和使用解耦了,花式的去使用对象的行为来完成特定场景下的功能。
94 0
我学会了,状态模式
|
存储 程序员 开发工具
状态模式与备忘录模式(2)
状态模式与备忘录模式(2)
131 0
状态模式与备忘录模式(2)
|
存储 Java Spring
状态模式与备忘录模式(3)
状态模式与备忘录模式(3)
132 0
状态模式与备忘录模式(3)
|
uml
状态模式与备忘录模式(1)
状态模式与备忘录模式(1)
86 0
状态模式与备忘录模式(1)
策略模式和状态模式的区别
策略模式和状态模式的类图相同,目的都是为了解耦,但是还有很多的区别
214 0