状态模式:允许对象在内部状态改变时改变它的行为,对象看起来修改了它的类。

package state

import (
	"fmt"
)

type State interface {
	InsertQuarter(machine *GumballMachine)
	EjectQuarter(machine *GumballMachine)
	TurnCrank(machine *GumballMachine)
	Dispense(machine *GumballMachine)
}

type GumballMachine struct {
	state           State
	count           int
	soldOutState    State
	noQuarterState  State
	hasQuarterState State
	soldState       State
}

func (o *GumballMachine) SetState(state State) {
	o.state = state
}

func (o *GumballMachine) ReleaseBall() {
	fmt.Println("a gumball comes rolling out the slot...")
	if o.count != 0 {
		o.count = o.count - 1
	}
}

func (o *GumballMachine) InsertQuarter() {
	o.state.InsertQuarter(o)
}

func (o *GumballMachine) EjectQuarter() {
	o.state.EjectQuarter(o)
}

func (o *GumballMachine) TurnCrank() {
	o.state.TurnCrank(o)
}

func NewMachine() *GumballMachine {
	return &GumballMachine{
		state:           &NoQuarterState{},
		count:           10,
		soldOutState:    &SoldOutState{},
		soldState:       &SoldState{},
		hasQuarterState: &HasQuarterState{},
		noQuarterState:  &NoQuarterState{},
	}
}

type NoQuarterState struct {
}

type HasQuarterState struct {
}

type SoldOutState struct {
}

type SoldState struct {
}

func (NoQuarterState) InsertQuarter(machine *GumballMachine) {
	fmt.Println("You inserted a quarter")
	machine.SetState(machine.hasQuarterState)
}

func (NoQuarterState) EjectQuarter(machine *GumballMachine) {
	fmt.Println("You have not inserted a quarter")
}

func (NoQuarterState) TurnCrank(machine *GumballMachine) {
	fmt.Println("You have not inserted a quarter")
}

func (NoQuarterState) Dispense(machine *GumballMachine) {
	fmt.Println("You have not inserted a quarter")
}

func (*SoldState) InsertQuarter(machine *GumballMachine) {
	fmt.Println("Please wait, we are already giving you a gumbail")
}

func (*SoldState) EjectQuarter(machine *GumballMachine) {
	fmt.Println("Sorry, you already turned the crank")
}

func (*SoldState) TurnCrank(machine *GumballMachine) {
	fmt.Println("turning twice does not get you another gumball")
}

func (*SoldState) Dispense(machine *GumballMachine) {
	machine.ReleaseBall()
	if machine.count > 0 {
		machine.SetState(machine.noQuarterState)
	} else {
		machine.SetState(machine.soldOutState)
	}
}

func (*SoldOutState) InsertQuarter(machine *GumballMachine) {

}

func (*SoldOutState) EjectQuarter(machine *GumballMachine) {

}

func (*SoldOutState) TurnCrank(machine *GumballMachine) {

}

func (*SoldOutState) Dispense(machine *GumballMachine) {

}

func (*HasQuarterState) InsertQuarter(machine *GumballMachine) {

}

func (*HasQuarterState) EjectQuarter(machine *GumballMachine) {

}

func (*HasQuarterState) TurnCrank(machine *GumballMachine) {

}

func (*HasQuarterState) Dispense(machine *GumballMachine) {

}