行为型 状态模式

为什么需要状态模式

首先状态机包含状态、事件、动作。

状态模式只是实现状态机的一种方法。实现状态机常见三种方法,一种是大量if else做分支跳转,实现简单维护困难;第二种是采用查表法,穷举状态转移的trigger/event以及对应的状态变化,极大提升代码可读性但是只适用于trigger比积简单的情形;第三种就是状态模式,如果状态不多,转移也简单但是trigger动作业务逻辑复杂,可以考虑这种模式。

实现

一般来说state的实现代码量非常大,大家慎重考虑啊。。。每个状态本身都要接受一个父类的输入,以便于改变父类对象指向自己的状态改变。

go.mod

module state

go 1.13

state.go

package state

type Week interface {
	Today() string
	Next(*DayContext)
}

type DayContext struct {
	today Week
}

func NewDayContext() *DayContext {
	return &DayContext{
		today: &Sunday{},
	}
}

func (ctx *DayContext) Today() string {
	return ctx.today.Today()
}

func (ctx *DayContext) Next() {
	ctx.today.Next(ctx)
}

type Sunday struct {
	ctx *DayContext
}

func (day *Sunday) Today() string {
	return "Sunday"
}

func (day *Sunday) Next(ctx *DayContext) {
	// This can be further optimized to use singleton to avoid new object
	ctx.today = &Monday{}
}

type Monday struct {
	ctx *DayContext
}

func (day *Monday) Today() string {
	return "Monday"
}

func (day *Monday) Next(ctx *DayContext) {
	ctx.today = &Sunday{}
}

state_test.go

package state_test

import (
	"state"
	"testing"
)

func TestState(t *testing.T) {
	dayContext := state.NewDayContext()
	if dayContext.Today() != "Sunday" {
		t.Fatal("Init error")
	}

	dayContext.Next()
	if dayContext.Today() != "Monday" {
		t.Fatal("State transfer error, expecting Monday")
	}

	dayContext.Next()
	if dayContext.Today() != "Sunday" {
		t.Fatal("State transfer error, expecting Sunday")
	}
}

执行: go test state -v

Previous
Next