本文转载自微信公众号「精益码农」,作者小码甲 。转载本文请联系精益码农公众号。

成都创新互联-专业网站定制、快速模板网站建设、高性价比临澧网站开发、企业建站全套包干低至880元,成熟完善的模板库,直接使用。一站式临澧网站制作公司更省心,省钱,快速模板网站建设找我们,业务覆盖临澧地区。费用合理售后完善,10年实体公司更值得信赖。
状态机是一种行为设计模式,它允许对象在其内部状态改变时改变其行为。看起来好像对象改变了它的类。
请仔细理解上面每一个字。
我们以自动售货机为例,为简化演示,我们假设自动售货机只有1种商品, 故自动售货机有itemCount 、itemPrice 2个属性。
不考虑动作的前后相关性,自动售货机对外暴露4种行为:
重点来了,当发生某种行为,自动售货机会进入如下4种状态之一, 并据此状态做出特定动作, 之后进入另外一种状态.....
当对象可能处于多种不同的状态之一、根据传入的动作更改当前的状态, 继续接受后续动作,状态再次发生变化.....
这样的模式类比于机器引擎,周而复始的工作和状态转化,这也是状态机的定语叫“机Machine”的原因。
有了以上思路,我们尝试沟通UML 伪代码:
状态机设计模式的伪代码实现:
下面使用golang实现了 状态机设计模型:这里你也可以看下golang 是如何体现OOP中的类继承、接口实现
goodMachine:状态变更上下文
- package main
 - import (
 - "fmt"
 - "reflect"
 - )
 - type goodMachine struct {
 - currentState state
 - itemCount int
 - itemPrice int
 - }
 - func newGoodMachine(itemCount, itemPrice int) *goodMachine {
 - v := &goodMachine{
 - itemCount: itemCount,
 - itemPrice: itemPrice,
 - }
 - if itemCount <= 0 {
 - v.setState(&noItemState{v}) // 实现state接口的是*noItemState 指针类型
 - } else {
 - v.setState(&hasItemState{v})
 - }
 - return v
 - }
 - func (v *goodMachine) setState(s state) {
 - fmt.Println("enter state: ", reflect.TypeOf(s))
 - v.currentState = s
 - }
 - func (v *goodMachine) requestItem() error {
 - return v.currentState.requestItem()
 - }
 - func (v *goodMachine) addItem(count int) error {
 - return v.currentState.addItem(count)
 - }
 - func (v *goodMachine) insertMoney(money int) error {
 - return v.currentState.insertMoney(money)
 - }
 - func (v *goodMachine) incrementItemCount(count int) {
 - v.itemCount += count
 - }
 - func (v goodMachine) dispenseItem() error {
 - return v.currentState.dispenseItem()
 - }
 
自动售货机对外的行为,被委托给特定的state对象
state:自动售货机对外暴露的行为
- package main
 - // 代表某种状态,能接受的某种动作
 - type state interface {
 - addItem(count int) error
 - requestItem() error
 - insertMoney(money int) error
 - dispenseItem() error
 - }
 
noItemState : 无商品
- package main
 - import "fmt"
 - type noItemState struct {
 - *goodMachine // 存在匿名类型 goodMachine,类型是*goodMachine
 - }
 - // 给自动售货机供货-----> 有货状态
 - func (i *noItemState) addItem(count int) error {
 - i.incrementItemCount(count)
 - i.setState(&hasItemState{i.goodMachine})
 - return nil
 - }
 - func (i *noItemState) requestItem() error {
 - return fmt.Errorf("item out of stock")
 - }
 - func (i *noItemState) insertMoney(money int) error {
 - return fmt.Errorf("item out of stock")
 - }
 - func (i *noItemState) dispenseItem() error {
 - return fmt.Errorf("item out of stock")
 - }
 - // golang: 使用指针接受者实现了state接口的全部函数,那么隐式表明*noItemState 指针类型实现了State接口
 
注意:noItemState 结构体内定义了 goodMachine, 就表明noItemState继承了goodMachine类 ;
指针接受者 noItemState实现了state接口的所有函数,那么我们就说*noItemState实现了state接口。
hasItemState: 有商品
- package main
 - import "fmt"
 - type hasItemState struct {
 - *goodMachine
 - }
 - func (v *hasItemState) addItem(count int) error {
 - v.incrementItemCount(count)
 - return nil
 - }
 - // 有人选择了商品---> 没货状态/已经选定商品
 - func (v *hasItemState) requestItem() error {
 - if v.goodMachine.itemCount == 0 {
 - v.setState(&noItemState{v.goodMachine})
 - return fmt.Errorf("no item present")
 - }
 - fmt.Print("item requested\n")
 - v.setState(&itemRequestedState{v.goodMachine})
 - return nil
 - }
 - func (v *hasItemState) insertMoney(money int) error {
 - return fmt.Errorf("Please select item first")
 - }
 - func (v *hasItemState) dispenseItem() error {
 - return fmt.Errorf("Please select item first")
 - }
 
itemRequestedState:有人选定商品
- package main
 - import "fmt"
 - type itemRequestedState struct {
 - *goodMachine
 - }
 - func (i *itemRequestedState) addItem(count int) error {
 - return fmt.Errorf("shopping is in process")
 - }
 - func (i *itemRequestedState) requestItem() error {
 - return fmt.Errorf("item already requested")
 - }
 - // 付钱----> 已收钱状态
 - func (i *itemRequestedState) insertMoney(money int) error {
 - if money < i.goodMachine.itemPrice {
 - fmt.Errorf("insert money is less, please insert %d", i.goodMachine)
 - }
 - fmt.Println("money entered is ok")
 - i.setState(&hasMoneyState{i.goodMachine})
 - return nil
 - }
 - func (i *itemRequestedState) dispenseItem() error {
 - return fmt.Errorf("please insert money first")
 - }
 
hasMoneyState:已付钱
- package main
 - import "fmt"
 - type hasMoneyState struct {
 - *goodMachine
 - }
 - func (i *hasMoneyState) addItem(count int) error {
 - return fmt.Errorf("shopping is in process")
 - }
 - func (i *hasMoneyState) requestItem() error {
 - return fmt.Errorf("shopping is in process")
 - }
 - func (i *hasMoneyState) insertMoney(money int) error {
 - return fmt.Errorf("already pay money")
 - }
 - func (i *hasMoneyState) dispenseItem() error {
 - fmt.Println("dispensing item")
 - i.goodMachine.itemCount = i.goodMachine.itemCount - 1
 - if i.goodMachine.itemCount == 0 {
 - i.setState(&noItemState{i.goodMachine})
 - } else {
 - i.setState(&hasItemState{i.goodMachine})
 - }
 - return nil
 - }
 
main.go 执行
- package main
 - import (
 - "fmt"
 - "log"
 - )
 - func main() {
 - goodMachine := newGoodMachine(1, 10)
 - err := goodMachine.requestItem()
 - if err != nil {
 - log.Fatalf(err.Error())
 - }
 - err = goodMachine.insertMoney(10)
 - if err != nil {
 - log.Fatalf(err.Error())
 - }
 - err = goodMachine.dispenseItem()
 - if err != nil {
 - log.Fatalf(err.Error())
 - }
 - fmt.Println()
 - err = goodMachine.requestItem()
 - if err != nil {
 - log.Fatalf(err.Error())
 - }
 - err = goodMachine.insertMoney(10)
 - if err != nil {
 - log.Fatal(err.Error())
 - }
 - err = goodMachine.dispenseItem()
 - if err != nil {
 - log.Fatalf(err.Error())
 - }
 - }
 
初始化了商品数量为1,价格为10 的自动售货机,连续掏10元钱买两次, 随时打印状态, 输出如下:
- enter state: *main.hasItemState
 - item requested
 - enter state: *main.itemRequestedState
 - money entered is ok
 - enter state: *main.hasMoneyState
 - dispensing item
 - enter state: *main.noItemState
 - 2021/08/11 17:39:45 item out of stock
 - exit status 1
 
状态机为什么定语是机器?Machine?
状态机表现了:
对象的状态受外界行为所影响,不断的切换,到达特定的状态又只能接受特定的行为, 真实生动的体现了机器Machine引擎的特征。
本文示例亦是学习golang OOP编程的范例,golang 类继承、接口实现实在是太秀了。
github: https://github.com/zaozaoniao/statemachine
                网页名称:我是状态机,一颗永远骚动的机器引擎
                
                文章源于:http://www.csdahua.cn/qtweb/news27/198327.html
            
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网