FSM:finite state machion,有限状态机。
两种实现方式:
适用于简单的状态机
int stateMachion(int event)
{
switch(curSate)
{
case sleeping:
switch(event)
{
case hungary:
eatIt();
curState = eating;
......
}
......
}
}
状态机要素:
初始状态
当前状态
状态迁移,上一个状态退出,下一个状态进入。
状态机运行的3个对象:
状态类
将每个状态抽象出状态类,每个状态都有进入、退出函数,另外加一个状态中执行的函数。
状态机类
表示状态机的参数,当前状态、提供状态迁移辅助函数;
外部驱动:
外部驱动状态机切换状态,可以是直接调用状态机切换状态,也可以是事件驱动,状态机处理事件,自行切换状态。
执行流:
外部驱动 => 状态机 => 状态。
struct state {
enter();
exit();
stay();
}
struct stateMachion{
/*当前状态*/
curState();
/*状态迁移函数*/
switchState();
}
适用于switch case情况,直接将状态迁移条件传入即可。
stateMachion(hungary);
stateMachion(sleepy);
状态机中增加事件处理函数,执行每个状态的事件处理函数。
事件驱动状态机的状态推进有事件推动,不同状态下对应不同事件处理函数.
状态类
增加每个状态事件处理函数。
struct state {
enter();
exit();
stay();
eventHandler();
}
状态机类
添加事件处理总入口
struct stateMachion {
curState();
switchState();
eventHandler();
}
事件驱动状态机。以一个人一天的生活状态为例。
使用go语言编程
1)状态定义
type STATE_TYPE int
/*状态*/
const (
STATE_SLEEPING STATE_TYPE = iota
STATE_EATING
STATE_GAMING
STATE_END
)
2)事件定义
type EVENT_TYPE int
/*事件*/
const (
EVENT_SLEEPY EVENT_TYPE = iota
EVENT_HUNGARY
EVENT_BORING
EVENT_END
)
3)状态类
/*状态类*/
type STATE interface {
enter()
exit()
stay()
eventHandler(*STATE_MACHION, EVENT_TYPE)
}
4)状态机类
type STATE_MACHION struct {
curStateType STATE_TYPE
statePool map[STATE_TYPE]STATE
/*初始状态*/
initState()
/*添加状态*/
addState()
/*切换状态函数*/
switchToState()
}
package main
import (
"fmt"
"strings"
"time"
)
type STATE_TYPE int
/*状态*/
const (
STATE_SLEEPING STATE_TYPE = iota
STATE_EATING
STATE_GAMING
STATE_END
)
type EVENT_TYPE int
/*事件*/
const (
EVENT_SLEEPY EVENT_TYPE = iota
EVENT_HUNGARY
EVENT_BORING
EVENT_END
)
/*状态类*/
type STATE interface {
enter()
exit()
stay()
eventHandler(*STATE_MACHION, EVENT_TYPE)
}
/*sleeping状态*/
type stateSleep struct {
sleepState bool
}
func (state *stateSleep) enter() {
fmt.Println("okay, i'm to sleep, touch my bed!")
state.sleepState = true
state.stay()
}
func (state *stateSleep) exit() {
fmt.Println("i'm wakely, leave my bed!")
state.sleepState = false
}
func (state *stateSleep) stay() {
go func() {
for {
if state.sleepState == false {
break
}
fmt.Println("heng heng heng....")
time.Sleep(5 * time.Second)
}
}()
}
func (state *stateSleep) eventHandler(sm *STATE_MACHION, event EVENT_TYPE) {
switch event {
case EVENT_HUNGARY:
sm.switchToState(STATE_EATING)
break
case EVENT_BORING:
sm.switchToState(STATE_GAMING)
break
}
}
/*eating状态*/
type stateEating struct {
eatingState bool
}
func (state *stateEating) enter() {
fmt.Println("okay, i'm to eat, give my bowl!")
state.eatingState = true
state.stay()
}
func (state *stateEating) exit() {
fmt.Println("eat end, drow my bowl!")
state.eatingState = false
}
func (state *stateEating) stay() {
go func() {
for {
if state.eatingState == false {
break
}
fmt.Println("kuangci kuangci kuangci....")
time.Sleep(5 * time.Second)
}
}()
}
func (state *stateEating) eventHandler(sm *STATE_MACHION, event EVENT_TYPE) {
switch event {
case EVENT_SLEEPY:
sm.switchToState(STATE_SLEEPING)
break
case EVENT_BORING:
sm.switchToState(STATE_GAMING)
break
}
}
/*gaming状态*/
type stateGaming struct {
gamingState bool
}
func (state *stateGaming) enter() {
fmt.Println("start game, take my switch!")
state.gamingState = true
state.stay()
}
func (state *stateGaming) exit() {
fmt.Println("game over, destory the f*ck swith!")
state.gamingState = false
}
func (state *stateGaming) stay() {
go func() {
for {
if state.gamingState == false {
break
}
fmt.Println("nice... f*ck.... ")
time.Sleep(5 * time.Second)
}
}()
}
func (state *stateGaming) eventHandler(sm *STATE_MACHION, event EVENT_TYPE) {
switch event {
case EVENT_SLEEPY:
sm.switchToState(STATE_SLEEPING)
break
case EVENT_HUNGARY:
sm.switchToState(STATE_EATING)
break
}
}
/*状态机类*/
type STATE_MACHION struct {
curStateType STATE_TYPE
statePool map[STATE_TYPE]STATE
}
func (sm *STATE_MACHION) addState(stateType STATE_TYPE, state STATE) {
sm.statePool[stateType] = state
}
func (sm *STATE_MACHION) initState(stateType STATE_TYPE) {
sm.curStateType = stateType
sm.statePool[stateType].enter()
}
func (sm *STATE_MACHION) switchToState(stateType STATE_TYPE) {
sm.statePool[sm.curStateType].exit()
sm.statePool[stateType].enter()
sm.curStateType = stateType
}
func (sm *STATE_MACHION) eventHandler(event EVENT_TYPE) {
sm.statePool[sm.curStateType].eventHandler(sm, event)
}
func main() {
/*构造对象*/
staEat := stateEating{}
staSleep := stateSleep{}
staGame := stateGaming{}
sm := STATE_MACHION{}
/*添加状态*/
sm.statePool = make(map[STATE_TYPE]STATE)
sm.addState(STATE_SLEEPING, &staSleep)
sm.addState(STATE_EATING, &staEat)
sm.addState(STATE_GAMING, &staGame)
sm.initState(STATE_SLEEPING)
var inputChr string
for {
inputChr = ""
fmt.Scanln(&inputChr)
fmt.Println(inputChr)
if strings.Compare(inputChr, "sleep") == 0 {
sm.eventHandler(EVENT_SLEEPY)
} else if strings.Compare(inputChr, "hungary") == 0 {
sm.eventHandler(EVENT_HUNGARY)
} else if strings.Compare(inputChr, "boring") == 0 {
sm.eventHandler(EVENT_BORING)
}
}
fmt.Println(EVENT_BORING)
}
为了可以动态添加状态而不修改原来的代码,可以加一个“由哪个状态可以切到我” 的处理函数,前面的eventhandler都是“我可以切到那些状态”。这样新加状态可以定义我能切到谁,谁可以切到我,原始的状态不需要修改。在事件处理时先匹配"我能切到谁",然后再遍历所有状态的”谁能切到我“。