【Go-设计模式】状态模式 详解

shadowLogo

概念:

状态模式用于 分离 状态行为

主要用来解决对象在 多种状态转换 时,需要对外输出 不同的行为 的问题

状态行为 是一一对应的,状态之间 可以 相互转换

当一个对象的 内在状态 改变时,允许 改变其行为
72


UML:

uml

  • Context
    环境角色,用于 维护 State 实例,这个实例定义 当前状态
  • State
    抽象状态角色,定义一个 接口封装Context 的 一个 特点接口相关行为
  • ConcreteState
    具体的状态角色每个子类 实现 一个与 Context的 一个状态相关行为

示例:

环境对象:

type Context struct {
	State State
}

func (this *Context) StartProcess() {
	this.State.ShowState()
	this.State.NextState(this)
}

func NewContext(initStateVal int64) Context {
	return Context{
		State: ConcreteState1{
			Attr1: initStateVal,
		},
	}
}

抽象的状态 功能接口:

type State interface {
	ShowState()
	NextState(ctx *Context)
}

具体的 状态类:

具体的 状态类1:

type ConcreteState1 struct {
	Attr1 int64
}

func (this ConcreteState1) ShowState() {
	fmt.Println("当前状态为:", this.Attr1)
}

func (this ConcreteState1) NextState(ctx *Context) {
	ctx.State = ConcreteState2{
		Attr1: 2,
	}
}

具体的 状态类2:

type ConcreteState2 struct {
	Attr1 int64
}

func (this ConcreteState2) ShowState() {
	fmt.Println("当前状态为:", this.Attr1)
}

func (this ConcreteState2) NextState(ctx *Context) {
	ctx.State = ConcreteState3{
		Attr1: 3,
	}
}

具体的 状态类3:

type ConcreteState3 struct {
	Attr1 int64
}

func (this ConcreteState3) ShowState() {
	fmt.Println("当前状态为:", this.Attr1)
}

func (this ConcreteState3) NextState(ctx *Context) {
	ctx.State = ConcreteState1{
		Attr1: 1,
	}
}

测试:

package main

import (
	"DemoProject/design/base23/state" // 根据自己的项目路径定制
)

func main() {
	// state
	context := state.NewContext(1)
	for i := 0; i < 5; i++ {
		context.StartProcess()
	}
}

注意事项:

优点:

  • 代码有很强的 可读性
    状态模式 将 每个状态的行为 封装到 对应的一个类中

  • 方便维护
    容易产生问题if-else 语句 删除了,如果把 每个状态的行为 都放到 一个类 中,
    如果 每次调用方法 时都要判断 当前是什么状态,不但会产出 很多 if-else 语句,而且容易出错

  • 符合“开闭原则
    容易增删状态

缺点:

会产生很多类
每个状态都要一个对应的类,当状态过多时会产生很多类,加大维护难度

应用场景:

当一个事件或者对象有 很多种状态,状态之间会 相互转换,对 不同的状态 要求有 不同的行为 的时候, 可以考虑使用 状态模式

posted @ 2021-12-17 14:30  在下右转,有何贵干  阅读(101)  评论(0)    收藏  举报