行为设计模式——状态模式

状态(State)模式是一种行为设计模式,是一种基于有限状态机制的设计模式。在这种设计模式中,行为是由相应的状态来决定的。

如果一个对象的实现方法会根据自身的状态而改变,就可以使用状态模式。

比如主播创建了一个直播计划,直播计划的状态最初是“未开始”,可以执行 Start 和 Stop 方法来开始直播和关闭直播,还可以通过 Cancel 方法取消直播计划。

当执行 Start 方法后,直播计划的状态变为“直播中”,在此状态下再次执行 Start 方法开始直播则不会执行开始动作,而是返回“执行失败,该直播已开始”。 直播未开始时执行 Stop 方法,则返回“执行失败,该直播未开始”;如果直播计划的状态已经是“直播中”,调用 Stop 直播状态将变为“已结束”,已结束的直播再次执行 Stop 方法则不会执行关闭动作,而是返回“执行失败,该直播已结束”。 当直播计划是“已取消”状态时,不管调 Start 还是 Stop,都将返回“执行失败,该直播已取消”。只有“未开始”的直播才能被取消。

这只是一个简单的例子,如果用 if…else… 判断,可以想象代码将会十分臃肿,且容易出错。

使用状态模式,我们将为一个直播计划对象提供 4 种状态下的 Start、Stop 和 Cancel 方法:

  • “未开始”状态下:Start 方法返回“直播中”,Stop 方法返回“执行失败,该直播未开始”,Cancel 方法返回“已取消”
  • “直播中”状态下:Start 方法返回“执行失败,该直播已开始”,Stop 方法返回“已结束”,Cancel 方法返回“执行失败,该直播已开始”
  • “已结束”状态下:Start 方法返回“执行失败,该直播已结束”,Stop 方法返回“执行失败,该直播已结束”,Cancel 方法返回“执行失败,该直播已结束”
  • “已取消”状态下:Start 方法返回“执行失败,该直播已取消”,Stop 方法返回“直播已取消”,Cancel 方法返回“执行失败,该直播已取消”

示例代码:

package main

import "fmt"

// 状态接口
type Stater interface {
	Start(*Live)
	Stop(*Live)
	Cancel(*Live)
}

// 直播计划的具体4种状态之——未开始
type StateNotStarted struct{}

func (s *StateNotStarted) Start(l *Live) {
	fmt.Println("Do Start:", l.ID+"直播中")
}

func (s *StateNotStarted) Stop(l *Live) {
	fmt.Println("Do Stop:", l.ID+"执行失败,该直播未开始")
}

func (s *StateNotStarted) Cancel(l *Live) {
	fmt.Println("Do Cancel:", l.ID+"已取消")
}

// 直播计划的具体4种状态之——直播中
type StateLiving struct{}

func (s *StateLiving) Start(l *Live) {
	fmt.Println("Do Start:", l.ID+"执行失败,该直播已开始")
}

func (s *StateLiving) Stop(l *Live) {
	fmt.Println("Do Stop:", l.ID+"已结束")
}

func (s *StateLiving) Cancel(l *Live) {
	fmt.Println("Do Cancel:", l.ID+"执行失败,该直播已开始")
}

// 直播计划的具体4种状态之——已结束
type StateEnded struct{}

func (s *StateEnded) Start(l *Live) {
	fmt.Println("Do Start:", l.ID+"执行失败,该直播已结束")
}

func (s *StateEnded) Stop(l *Live) {
	fmt.Println("Do Stop:", l.ID+"执行失败,该直播已结束")
}

func (s *StateEnded) Cancel(l *Live) {
	fmt.Println("Do Cancel:", l.ID+"执行失败,该直播已结束")
}

// 直播计划的具体4种状态之——已取消
type StateCanceled struct{}

func (s *StateCanceled) Start(l *Live) {
	fmt.Println("Do Start:", l.ID+"执行失败,该直播已取消")
}

func (s *StateCanceled) Stop(l *Live) {
	fmt.Println("Do Stop:", l.ID+"执行失败,该直播已取消")
}

func (s *StateCanceled) Cancel(l *Live) {
	fmt.Println("Do Stop:", l.ID+"执行失败,该直播已取消")
}

// 直播计划
type Live struct {
	ID           string
	CurrentState Stater
}

func (l *Live) Start() {
	l.CurrentState.Start(l)
}

func (l *Live) Stop() {
	l.CurrentState.Stop(l)
}

func (l *Live) Cancel() {
	l.CurrentState.Cancel(l)
}

func (l *Live) SetState(s Stater) {
	l.CurrentState = s
}

func main() {

	var state Stater
	// 未开始状态
	live := &Live{ID: "001"}
	fmt.Println("Live" + live.ID + "当前状态:未开始")
	state = &StateNotStarted{}
	live.SetState(state)
	live.Start()
	live.Stop()
	live.Cancel()
	fmt.Println("-----------")

	// 直播中状态
	live = &Live{ID: "002"}
	fmt.Println("Live" + live.ID + "当前状态:直播中")
	state = &StateLiving{}
	live.SetState(state)
	live.Start()
	live.Stop()
	live.Cancel()
	fmt.Println("-----------")

	// 已结束状态
	live = &Live{ID: "003"}
	fmt.Println("Live" + live.ID + "当前状态:已结束")
	state = &StateEnded{}
	live.SetState(state)
	live.Start()
	live.Stop()
	live.Cancel()
	fmt.Println("-----------")

	// 已取消状态
	live = &Live{ID: "004"}
	fmt.Println("Live" + live.ID + "当前状态:已取消")
	state = &StateCanceled{}
	live.SetState(state)
	live.Start()
	live.Stop()
	live.Cancel()
}

运行示例代码,输出结果:

Live001当前状态:未开始
Do Start: 001直播中
Do Stop: 001执行失败,该直播未开始
Do Cancel: 001已取消
-----------
Live002当前状态:直播中
Do Start: 002执行失败,该直播已开始
Do Stop: 002已结束
Do Cancel: 002执行失败,该直播已开始
-----------
Live003当前状态:已结束
Do Start: 003执行失败,该直播已结束
Do Stop: 003执行失败,该直播已结束
Do Cancel: 003执行失败,该直播已结束
-----------
Live004当前状态:已取消
Do Start: 004执行失败,该直播已取消
Do Stop: 004执行失败,该直播已取消
Do Cancel: 004执行失败,该直播已取消

也可以看看


全国大流量卡免费领

19元月租ㆍ超值优惠ㆍ长期套餐ㆍ免费包邮ㆍ官方正品