概念
在狀態(tài)模式(State Pattern),當(dāng)一個(gè)對(duì)象的內(nèi)在狀態(tài)改變時(shí)允許改變其行為,這個(gè)對(duì)象看起來(lái)像是改變了其類(lèi)。
狀態(tài)模式主要解決的是當(dāng)控制一個(gè)對(duì)象狀態(tài)轉(zhuǎn)換的條件表達(dá)式過(guò)于復(fù)雜時(shí)的情況驹暑,把狀態(tài)的判斷邏輯轉(zhuǎn)移到表示不同狀態(tài)的一系列類(lèi)當(dāng)中, 可以把復(fù)雜的邏輯簡(jiǎn)化辨赐。當(dāng)然优俘, 如果這個(gè)狀態(tài)判斷很簡(jiǎn)單,就沒(méi)有必要使用'狀態(tài)模式'了掀序。
UML類(lèi)圖
statepattern.png
使用場(chǎng)景和優(yōu)缺點(diǎn)
使用場(chǎng)景
代碼中包含大量與對(duì)象狀態(tài)有關(guān)的條件語(yǔ)句, 當(dāng)一個(gè)對(duì)象的行為取決于他的狀態(tài)兼吓, 并且他必須在運(yùn)行時(shí)刻根據(jù)狀態(tài)改變他的行為時(shí), 既可以考慮使用狀態(tài)模式了森枪。
優(yōu)點(diǎn)
- 行為和狀態(tài)解耦
將與特定狀態(tài)相關(guān)的行為局部話, 并且將不同的狀態(tài)的行為分割開(kāi)來(lái)审孽。
- 易擴(kuò)展
將所有與某個(gè)狀態(tài)有關(guān)的行為放到一個(gè)類(lèi)中县袱,并且可以方便地增加新的狀態(tài),只需要改變對(duì)象狀態(tài)即可改變對(duì)象的行為
- 簡(jiǎn)化邏輯
- 消除了龐大的條件分支語(yǔ)句佑力, 將某一類(lèi)狀態(tài)的行為放到同一個(gè)類(lèi)中式散。
- 可以讓多個(gè)環(huán)境對(duì)象共享一個(gè)狀態(tài)對(duì)象,從而減少系統(tǒng)中對(duì)象的個(gè)數(shù)打颤。
缺點(diǎn)
- 狀態(tài)模式的使用必然會(huì)增加系統(tǒng)類(lèi)和對(duì)象的個(gè)數(shù)
- 狀態(tài)模式的結(jié)構(gòu)與實(shí)現(xiàn)都較為復(fù)雜暴拄,如果使用不當(dāng)將導(dǎo)致程序結(jié)構(gòu)和代碼的混亂
- 狀態(tài)模式對(duì)"開(kāi)閉原則"的支持并不太好漓滔,對(duì)于可以切換狀態(tài)的狀態(tài)模式,增加新的狀態(tài)類(lèi)需要修改那些負(fù)責(zé)狀態(tài)轉(zhuǎn)換的源代碼乖篷,否則無(wú)法切換到新增狀態(tài)响驴,而且修改某個(gè)狀態(tài)類(lèi)的行為也需修改對(duì)應(yīng)類(lèi)的源代碼
代碼實(shí)現(xiàn)
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("當(dāng)前時(shí)間:%v點(diǎn),上午工作 精神百倍", work.Hour)
} else {
work.SetState(&NoonState{})
work.WriteProgram()
}
}
type NoonState struct {
}
func (n *NoonState) WriteProgram(work Work) {
if work.Hour < 13 {
fmt.Printf("當(dāng)前時(shí)間:%v點(diǎn)撕蔼,餓了 午飯 犯困 午休", work.Hour)
} else {
work.SetState(&AfternoonState{})
work.WriteProgram()
}
}
type AfternoonState struct {
}
func (a *AfternoonState) WriteProgram(work Work) {
if work.Hour < 17 {
fmt.Printf("當(dāng)前時(shí)間:%v點(diǎn)豁鲤,下午狀態(tài)還不錯(cuò) 繼續(xù)努力", 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("當(dāng)前時(shí)間:%v點(diǎn),加班哦 疲累至極", work.Hour)
} else {
work.SetState(&SleepState{})
work.WriteProgram()
}
}
}
type RestState struct {
}
func (r *RestState) WriteProgram(work Work) {
fmt.Printf("當(dāng)前時(shí)間:%v點(diǎn)鲸沮,下班回家了", work.Hour)
}
type SleepState struct {
}
func (s *SleepState) WriteProgram(work Work) {
fmt.Printf("當(dāng)前時(shí)間:%v點(diǎn)琳骡,不行了 睡著了", work.Hour)
}
func main() {
//狀態(tài)模式
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()
}