状态机

2021-09-26 11:33:24 浏览数 (2)

这篇文章并不刻意介绍状态机的学术概念,只想谈谈状态机的实际运用。如果想看系统性的学术介绍的话,可以查看百度百科。

百度百科:状态机

应用场景

同学们在工作中,有没有遇到过类似这样的代码。

代码语言:javascript复制
if (/*  n个判断条件 */) {
    // 200行代码 
} else if (/*  n个判断条件 */)) {
    // 300行代码 
} else if (/*  n个判断条件 */) {
    // 量之大,一屏装不下
} else if (/*  n个判断条件 */) {
    // 量之大,一屏装不下
}
...................

如果安排你去维护这样一段代码,你会怎么做?

是浪费大量时间、枉死无数脑细胞去梳理其中的逻辑关系和方法,顺便抱怨一句“祖传代码真可恶”;还是会采用更好的结构(设计模式)去重构这些充满恶意的代码呢?

状态机模式就是用于处理这样一种复杂的逻辑判断结构的设计模式。

结构分析

在实现状态机时:

  • 一个条件分支可以认为是一种状态(state)。
  • 判断条件成立时(event),则执行对应的方法体(action)。
  • 如果环境变量改变,以致不同分支的判断条件成立,则执行不同分支的方法体,这称为状态转换(transition)。

以上也就是状态机的四大概念:state、event、action、transition。

用法示例

假如业务想要做一个下滑翻屏的 Swiper 页面,每一屏都有不同的内容和动画。为了提高性能,我们希望用户进入该屏时,再播放该屏的动画,此时就可以使用状态机来实现这一场景。

代码语言:javascript复制
class MovieActionState1 {
	constructor () {}
	update () {
		// Action: 第一屏动画
	}
}

class MovieActionState2 {
	constructor () {}
	update () {
		// Action: 第二屏动画
	}
}

class MovieActionState3 {
	constructor () {}
	update () {
		// Action: 第三屏动画
	}
}

class Movie {
	actionState1; // State:第一屏
	actionState2; // State:第二屏
	actionState3; // State:第三屏

	nowState; // 现态

	constructor () {
		this.actionState1 = new MovieActionState1()
		this.actionState2 = new MovieActionState2()
		this.actionState3 = new MovieActionState3()
		this.nowState = this.actionState1
	}

	run (context) {
		let ctx = context || this // 保证this指向的地址可被访问
		if (ctx.nowState) {
			ctx.nowState.update()
		}
		window.requestAnimationFrame(function () {
			ctx.run(ctx)
		})
	}

	toggleState (index) { // Event
		switch (index) {
			case 0:
				this.nowState = this.actionState1 // Transition
				break;
			case 1: 
				this.nowState = this.actionState2
				break;
			case 2: 
				this.nowState = this.actionState3
				break;
		}
	}
}

测试:

代码语言:javascript复制
let movie = new Movie()
new Swiper ('.swiper-container', { // 需要引入第三方 Swiper 库
	on: {
		init () {
			movie.run()
		},
		slideChange () {
			movie.toggleState(this.activeIndex)
		}
	}
})

假如此时业务需要再加一屏动画,那么可以创建并实例化一个 MovieActionState4,并在 toggleState 中写上状态的触发条件和转换语句。这种结构清晰易读,要比写个几百上千行的条件分支结构要好维护多了。

0 人点赞