有限状态机用来描述通过类的不同状态来完成对类的行为动作的转换,我们可以方便的使用状态模式来实现简单的有限状态机。
FSM有限状态机原理
FSM有限状态机是一种数学模型,表示系统或程序行为随状态变化而进行相应的动作流转。其中状态是有限的,而每个状态对应的动作也是确定的,状态在一定条件下可以进行转化。
SM的状态机设计要点包括确定状态集合、转移函数、初始状态和结束状态,绘制状态图和转移表格,以及状态机的实现。其设计要点包括以下几个方面:
- 确定状态集合:需要明确系统可能的所有状态,并将其表示为一个状态集合。状态集合应该包含系统的所有可能状态。
- 确定转移函数:需要确定系统从一个状态到另一个状态的转移函数。这可以通过定义每个状态之间的转移条件和对应的动作来实现。转移条件可以是输入信号、计时器到期等等。
- 确定初始状态:需要指定系统的初始状态。通常情况下,系统的初始状态是指系统在运行前处于的状态。
- 确定结束状态:需要指定系统的结束状态。结束状态是指系统在某些条件下停止的状态,通常情况下,结束状态是指系统达到一种特定的状态。
- 状态机的实现:需要将状态机转换为程序代码,以便于在计算机上运行和控制。在实现时需要考虑状态机的可重入性、可移植性、可靠性等因素。
该模型在设计模式上与状态模式和策略模式很相似:
FSM的状态即可理解为一种状态类,状态对应的行为实际是状态类的实现;状态也可以理解为一种策略参数,对应不同的行为策略。
状态模式实现有限状态机
状态模式核心点是:状态模式允许对象通过修改其状态来改变行为,在外界看来是修改了一种类。整体看起来是外界只需要修改对象的状态,即可完成动作行为的自动切换。
状态模式主要解决的是,当代码中有大量因状态或属性发生变化而产生的条件语句时,就可以将状态或属性的枚举值抽象为状态类,通过状态的流转实现相应行为的切换。
而对于FSM场景,不同的状态有各自的状态流向以及流转逻辑。以订单为例,用户侧可以针对订单进行下单、支付、退款等操作,而相应订单的状态就是待支付、已支付、已退款。
package main
import "fmt"
// 订单有3种状态 paying - paid - cancel
type OrderState interface {
// 订单行为: 下单 支付 取消
create() OrderState
pay() OrderState
cancel() OrderState
// 查询类
getState() string
}
type orderLooking struct {
}
func (s *orderLooking) create() OrderState {
fmt.Println("下单成功,done")
return &orderPaying{}
}
func (s *orderLooking) pay() OrderState {
fmt.Println("warning:暂无订单")
return s
}
func (s *orderLooking) cancel() OrderState {
fmt.Println("warning:暂无订单,不可取消")
return s
}
func (s *orderLooking) getState() string {
return "闲逛中"
}
type orderPaying struct {
}
func (s *orderPaying) create() OrderState {
fmt.Println("warning:已有订单,请勿重复下单,请支付")
return s
}
func (s *orderPaying) pay() OrderState {
fmt.Println("支付订单,done")
return &orderPaid{}
}
func (s *orderPaying) cancel() OrderState {
fmt.Println("warning:未支付,不可取消")
return s
}
func (s *orderPaying) getState() string {
return "待支付状态"
}
type orderPaid struct {
}
func (s *orderPaid) create() OrderState {
fmt.Println("warning:订单已支付,请勿重复下单")
return s
}
func (s *orderPaid) pay() OrderState {
fmt.Println("warning:订单已支付,请勿重复支付")
return s
}
func (s *orderPaid) cancel() OrderState {
fmt.Println("取消订单,done")
return &orderCancel{}
}
func (s *orderPaid) getState() string {
return "已支付状态"
}
type orderCancel struct {
}
func (s *orderCancel) create() OrderState {
fmt.Println("订单已取消,请继续浏览")
return &orderLooking{}
}
func (s *orderCancel) pay() OrderState {
fmt.Println("warning:暂无进行中订单")
return &orderLooking{}
}
func (s *orderCancel) cancel() OrderState {
fmt.Println("warning:暂无可取消订单")
return &orderLooking{}
}
func (s *orderCancel) getState() string {
return "已取消状态"
}
// 订单承载器JD
type jdShop struct {
state OrderState
}
func (jd *jdShop) looking() {
fmt.Println("冰糖葫芦~", jd.state.getState())
}
func (jd *jdShop) buy() {
jd.state = jd.state.create()
}
func (jd *jdShop) pay() {
jd.state = jd.state.pay()
}
func (jd *jdShop) cancel() {
jd.state = jd.state.cancel()
}
func main() {
shop := &jdShop{state: &orderLooking{}}
shop.looking()
shop.pay()
shop.looking()
fmt.Println("------我饿了------")
shop.buy()
shop.pay()
shop.cancel()
}
// 执行结果
冰糖葫芦~ 闲逛中
warning:暂无订单
冰糖葫芦~ 闲逛中
------我饿了------
下单成功,done
支付订单,done
取消订单,done