1. 概念
1.1 作用
状态(State)指状态对象,用于封装上下文对象的特定状态行为,使得上下文对象在内部状态改变时能够改变其自身的行为。
1.1 角色
- Context(环境类角色):内部维护一个当前状态实例,并负责具体状态的切换。
- State(抽象状态角色):
- 是所有具体状态的抽象接口
- 它的每一个方法代表了环境类的一种操作
- ConcreteState(具体状态角色):
- 每个ConcreteState都代表了环境类的一个状态
- 它的每一个方法代表了环境类在该状态下的一种行为(环境在不同状态下,同一行为的操作是不同的)
1.2 类图
2. 代码示例
2.1 设计
需求
- 环境有关闭、受限、正常三个状态
- 环境有查看、评论、发布三种状态
- 其对应关系如下:
查看 评论 发布 正常 √ √ √ 受限 √ √ × 关闭 × × ×
- 定义环境类Context
- 它依赖了抽象状态(如果状态没有冲突,你也可以写成状态的聚合)
- 它有一个成员是健康值
- 它的一个内部方法,用来修改状态(虽然golang没有java对类的权限控制,我们只能这么理解,尽量不在“类之外调用”)
- 它的一个外部方法,传入健康值同时修改环境状态
- 定义一个函数,创建环境类(这不是状态模式的重点,仅为了方便实例化)
- 定义抽象状态State
- 定义一个具体状态
关闭
(模拟一个网站的用户状态)- 它的
View()
方法,模式关闭
状态用户不能查看 - 它的
Comment()
方法,模拟关闭
状态用户不能评论 - 它的
Post()
方法,模拟关闭
状态用户不能发布
- 它的
- 定义一个具体状态
限制
(模拟一个网站的用户状态)- 它的
View()
方法,模式限制
状态用户可以查看 - 它的
Comment()
方法,模拟限制
状态用户可以评论 - 它的
Post()
方法,模拟限制
状态用户不能发布
- 它的
- 定义一个具体状态
正常
(模拟一个网站的用户状态)- 它的
View()
方法,模式正常
状态用户可以查看 - 它的
Comment()
方法,模拟正常
状态用户可以评论 - 它的
Post()
方法,模拟正常
状态用户可以发布
- 它的
- 调用
- 实例化一个环境类
- 执行查看操作
- 修改环境类健康值
- 再次执行查看操作
2.2 代码
- 代码
package main
import (
"fmt"
)
// 定义环境类
type Context struct {
state State
HealthValue int
}
// 根据环境类健康值修改环境状态
func (c *Context) changeState() {
if c.HealthValue <= -10 {
c.state = &Close{}
} else if c.HealthValue > -10 && c.HealthValue <= 0 {
c.state = &Restriction{}
} else if c.HealthValue > 0 {
c.state = &Normal{}
}
}
// 设置环境类健康值
func (c *Context) SetHealth(value int) {
c.HealthValue = value
c.changeState()
}
// 创建环境类
func CreateContext(health int) *Context {
a := &Context{
HealthValue: health,
}
a.changeState()
return a
}
// 定义抽象状态类
type State interface {
View()
Comment()
Post()
}
// 定义第一个具体状态
type Close struct{}
func (c *Close) View() {
fmt.Println("无法查看")
}
func (c *Close) Comment() {
fmt.Println("不能评论")
}
func (c *Close) Post() {
fmt.Println("不能发布")
}
// 定义第二个具体状态
type Restriction struct{}
func (r *Restriction) View() {
fmt.Println("查看正常")
}
func (r *Restriction) Comment() {
fmt.Println("评论正常")
}
func (r *Restriction) Post() {
fmt.Println("不能发布")
}
// 定义第三个具体状态
type Normal struct{}
func (n *Normal) View() {
fmt.Println("查看正常")
}
func (n *Normal) Comment() {
fmt.Println("评论正常")
}
func (n *Normal) Post() {
fmt.Println("发布正常")
}
func main() {
context := CreateContext(75)
context.state.View()
fmt.Println("================改变健康值==========")
context.SetHealth(-20)
context.state.View()
}
- 输出
查看正常
================改变健康值==========
无法查看