概念
在状态模式(State Pattern),当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类。
状态模式主要解决的是当控制一个对象状态转换的条件表达式过于复杂时的情况,把状态的判断逻辑转移到表示不同状态的一系列类当中, 可以把复杂的逻辑简化。当然, 如果这个状态判断很简单,就没有必要使用'状态模式'了。
UML类图
使用场景和优缺点
使用场景
代码中包含大量与对象状态有关的条件语句, 当一个对象的行为取决于他的状态, 并且他必须在运行时刻根据状态改变他的行为时, 既可以考虑使用状态模式了。
优点
- 行为和状态解耦
将与特定状态相关的行为局部话, 并且将不同的状态的行为分割开来。
- 易扩展
将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为
- 简化逻辑
- 消除了庞大的条件分支语句, 将某一类状态的行为放到同一个类中。
- 可以让多个环境对象共享一个状态对象,从而减少系统中对象的个数。
缺点
- 状态模式的使用必然会增加系统类和对象的个数
- 状态模式的结构与实现都较为复杂,如果使用不当将导致程序结构和代码的混乱
- 状态模式对"开闭原则"的支持并不太好,对于可以切换状态的状态模式,增加新的状态类需要修改那些负责状态转换的源代码,否则无法切换到新增状态,而且修改某个状态类的行为也需修改对应类的源代码
代码实现
package main
import (
"fmt"
)
type IState interface {
WriteProgram(work Work)
}
type Work struct {
State IState
Hour float64
TaskFinish bool
}
func (w *Work) SetState(state IState) {
w.State = state
}
func (w *Work) WriteProgram() {
w.State.WriteProgram(*w)
}
type ForenoonState struct {
}
func (f *ForenoonState) WriteProgram(work Work) {
if work.Hour < 12 {
fmt.Printf("当前时间:%v点,上午工作 精神百倍", work.Hour)
} else {
work.SetState(&NoonState{})
work.WriteProgram()
}
}
type NoonState struct {
}
func (n *NoonState) WriteProgram(work Work) {
if work.Hour < 13 {
fmt.Printf("当前时间:%v点,饿了 午饭 犯困 午休", work.Hour)
} else {
work.SetState(&AfternoonState{})
work.WriteProgram()
}
}
type AfternoonState struct {
}
func (a *AfternoonState) WriteProgram(work Work) {
if work.Hour < 17 {
fmt.Printf("当前时间:%v点,下午状态还不错 继续努力", work.Hour)
} else {
work.SetState(&EveningState{})
work.WriteProgram()
}
}
type EveningState struct {
}
func (e *EveningState) WriteProgram(work Work) {
if work.TaskFinish {
work.SetState(&RestState{})
work.WriteProgram()
} else {
if work.Hour < 21 {
fmt.Printf("当前时间:%v点,加班哦 疲累至极", work.Hour)
} else {
work.SetState(&SleepState{})
work.WriteProgram()
}
}
}
type RestState struct {
}
func (r *RestState) WriteProgram(work Work) {
fmt.Printf("当前时间:%v点,下班回家了", work.Hour)
}
type SleepState struct {
}
func (s *SleepState) WriteProgram(work Work) {
fmt.Printf("当前时间:%v点,不行了 睡着了", work.Hour)
}
func main() {
//状态模式
emergencyProject := Work{State: &ForenoonState{}}
emergencyProject.Hour = 9
emergencyProject.WriteProgram()
fmt.Println()
emergencyProject.Hour = 10
emergencyProject.WriteProgram()
fmt.Println()
emergencyProject.Hour = 12
emergencyProject.WriteProgram()
fmt.Println()
emergencyProject.Hour = 13
emergencyProject.WriteProgram()
fmt.Println()
emergencyProject.Hour = 14
emergencyProject.WriteProgram()
fmt.Println()
emergencyProject.Hour = 17
emergencyProject.TaskFinish = true
emergencyProject.WriteProgram()
fmt.Println()
emergencyProject.Hour = 19
emergencyProject.WriteProgram()
fmt.Println()
emergencyProject.Hour = 22
emergencyProject.WriteProgram()
fmt.Println()
}