FSM有限状态机
FSM:finite state machion,有限状态机。
两种实现方式:
简单switch case
适用于简单的状态机
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)
}
TODO
为了可以动态添加状态而不修改原来的代码,可以加一个“由哪个状态可以切到我” 的处理函数,前面的eventhandler都是“我可以切到那些状态”。这样新加状态可以定义我能切到谁,谁可以切到我,原始的状态不需要修改。在事件处理时先匹配"我能切到谁",然后再遍历所有状态的”谁能切到我“。










