定义
当一个对象内部的状态发生改变时,会导致其行为的改变。这看起来像是改变了对象
理解
使用场景
当我们需要对多个状态进行判断和切换时
比如一个游戏角色可以跳跃、移动、射击、和蹲下,当他每次行动是我们都需要执行一次判断语句,这样对于代码的运行速度就会有很大的影响,而且不利于后期的维护和添加。
(function(state){if(state === 'jump'){console.log('跳跃!')}else if(state === 'move'){console.log('移动!')}else if(state === 'shoot'){console.log('射击!')}else if(state === 'squat'){console.log('蹲下!')}})(dice.satte)
步骤
1.将条件判断的结果转化为状态对象内部的状态(代码中的jump,move,shoot,squat),内部状态通常作为状态对象内部的私有变量
2.然后提供一个能够调用状态对象内部状态的接口方法对象(changeState,contraGo),
实现
class SuperMarry {constructor() {this._currentState = []this.states = {jump() {console.log('跳跃!')},move() {console.log('移动!')},shoot() {console.log('射击!')},squat() {console.log('蹲下!')}}}change(arr) { // 更改当前动作this._currentState = arrreturn 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() // 触发动作 蹲下!
总结
在实际开发中,很多场景都可以用状态机来模拟,比如一个下拉菜单在hover动作下有显示、悬浮、隐藏等状态;一次TCP请求有建立连接、监听、关闭等状态;一个格斗游戏中人物有攻击、防御、跳跃、跌倒等状态。
- 一个由一个或多个动态变化的属性导致发生不同行为的对象,在与外部事件产生互动时,其内部状态就会改变,从而使得系统的行为也随之发生变化,那么这个对象,就是有状态的对象
- 代码中包含大量与对象状态有关的条件语句,像是if else或switch case语句,且这些条件执行与否依赖于该对象的状态。
如果场景符合上面两个条件,那我们就可以想象状态模式是不是可以帮忙了
**
状态模式的优缺点:
优点:
- 一个状态状态对应行为,封装在一个类里,更直观清晰,增改方便
- 状态与状态间,行为与行为间彼此独立互不干扰
- 避免事物对象本身不断膨胀,条件判断语句过多
-
缺点:
需要将事物的不同状态以及对应的行为拆分出来,有时候会无法避免的拆分的很细,有的时候涉及业务逻辑,一个动作拆分出对应的两个状态,动作就拆不明白了,过度设计
- 必然会增加事物类和动作类的个数,有时候动作类再根据单一原则,按照功能拆成几个类,会反而使得代码混乱,可读性降低
**简而言之,当遇到很多同级if-else或者switch的时候,可以使用状态模式来进行简化。
**
