MST

星途 面试题库

面试题:Go语言中如何基于状态模式简单实现一个状态机

请使用Go语言,基于状态模式实现一个简单的状态机,比如一个自动售货机状态机,包含“等待投币”、“已投币可选择商品”、“出货中”等状态,并且要展示状态之间如何正确切换,写出关键代码片段并解释。
27.4万 热度难度
编程语言Go

知识考点

AI 面试

面试题答案

一键面试
package main

import (
    "fmt"
)

// 状态接口
type State interface {
    InsertCoin(machine *VendingMachine)
    SelectProduct(machine *VendingMachine)
    DispenseProduct(machine *VendingMachine)
}

// 等待投币状态
type WaitingForCoin struct{}

func (w *WaitingForCoin) InsertCoin(machine *VendingMachine) {
    fmt.Println("硬币已投入,进入已投币可选择商品状态")
    machine.State = &CoinInserted{}
}

func (w *WaitingForCoin) SelectProduct(machine *VendingMachine) {
    fmt.Println("请先投入硬币")
}

func (w *WaitingForCoin) DispenseProduct(machine *VendingMachine) {
    fmt.Println("请先投入硬币并选择商品")
}

// 已投币可选择商品状态
type CoinInserted struct{}

func (c *CoinInserted) InsertCoin(machine *VendingMachine) {
    fmt.Println("已经投币,无需再次投币")
}

func (c *CoinInserted) SelectProduct(machine *VendingMachine) {
    fmt.Println("商品已选择,进入出货中状态")
    machine.State = &Dispensing{}
}

func (c *CoinInserted) DispenseProduct(machine *VendingMachine) {
    fmt.Println("请先选择商品")
}

// 出货中状态
type Dispensing struct{}

func (d *Dispensing) InsertCoin(machine *VendingMachine) {
    fmt.Println("正在出货,请勿投币")
}

func (d *Dispensing) SelectProduct(machine *VendingMachine) {
    fmt.Println("正在出货,请勿选择商品")
}

func (d *Dispensing) DispenseProduct(machine *VendingMachine) {
    fmt.Println("商品已出货,回到等待投币状态")
    machine.State = &WaitingForCoin{}
}

// 自动售货机
type VendingMachine struct {
    State State
}

func NewVendingMachine() *VendingMachine {
    return &VendingMachine{
        State: &WaitingForCoin{},
    }
}

代码解释

  1. 状态接口(State):定义了状态机中每个状态都需要实现的方法,包括 InsertCoin(投币)、SelectProduct(选择商品)和 DispenseProduct(出货)。
  2. 等待投币状态(WaitingForCoin):实现了 State 接口。在该状态下,只有投币操作能使状态机进入“已投币可选择商品”状态,其他操作提示相应错误。
  3. 已投币可选择商品状态(CoinInserted):同样实现 State 接口。在此状态下,投币操作提示无需投币,选择商品操作使状态机进入“出货中”状态,出货操作提示先选择商品。
  4. 出货中状态(Dispensing):实现 State 接口。在这个状态下,投币和选择商品操作都被禁止,出货完成后状态机回到“等待投币”状态。
  5. 自动售货机(VendingMachine):包含一个 State 类型的字段,代表当前状态机所处的状态。NewVendingMachine 函数初始化状态机为“等待投币”状态。通过调用不同状态下的方法,实现状态机在不同状态间的正确切换。