场景
老板:我们现在要开发一个文档系统,支持多种模式,在预览模式下只支持预览操作.编辑模式下,支持增删改查操作,你有什么好的方案
你:好的老板,那就使用状态模式
方案
状态模式
:我们通过状态对象封装了对上下文的动作.用不同的状态对象维护着对上下文对象操作的不同实现,达到可以横向扩展的效果.
在这个例子中,我们把文档系统当成如图所示的上下文,里面维护几个不同的状态,预览状态、编辑状态,再把我们的增删改查的动作封装到这些状态里面,通过上下文对象去使用它们.以后我们如果要扩张其他的模式,增加一个状态即可.
注意,这里要区分跟策略模式
的区别,这些状态
是维护在上下文内部的,客户端直接操作上下文对象,不会操作到状态对象,状态对象作为上下文的一部分组成而存在.下面,我们看看对这个例子的实现
实现
package main
import "fmt"
type Stage interface {//状态接口
Add()
Delete()
Update()
Get()
}
type context struct {
currentState Stage//当前状态
currentStateIndex int//当前状态索引
innerStates []Stage//状态列表
}
func (ctx *context) ChangeState() {//切换状态
fmt.Println("切换状态")
ctx.currentStateIndex=ctx.currentStateIndex+1
ctx.currentStateIndex%=len(ctx.innerStates)
ctx.currentState=ctx.innerStates[ctx.currentStateIndex]
}
func (ctx *context) Work(){//上下文工作
ctx.currentState.Add()
ctx.currentState.Delete()
ctx.currentState.Update()
ctx.currentState.Get()
}
func Init() *context{//初始化一个上下文
ctx:=&context{
innerStates:[]Stage{&PreviewState{},&EditState{}},
}
ctx.currentStateIndex=0
ctx.currentState=ctx.innerStates[ctx.currentStateIndex]
return ctx
}
//下面是两个不同状态的实现
type PreviewState struct {
}
func (state *PreviewState) Add() {
fmt.Println("[预览模式]不支持增加操作")
}
func (state *PreviewState) Delete() {
fmt.Println("[预览模式]不支持删除操作")
}
func (state *PreviewState) Update() {
fmt.Println("[预览模式]不支持更新操作")
}
func (state *PreviewState) Get() {
fmt.Println("[预览模式]查阅文档")
}
type EditState struct {
}
func (state *EditState) Add() {
fmt.Println("[编辑模式]增加文档")
}
func (state *EditState) Delete() {
fmt.Println("[编辑模式]删除文档")
}
func (state *EditState) Update() {
fmt.Println("[编辑模式]更新文档")
}
func (state *EditState) Get() {
fmt.Println("[编辑模式]查阅文档")
}
func main(){
ctx:=Init()
ctx.Work()
ctx.ChangeState()
ctx.Work()
}