狀態模式:就像你的心情變化!
大家好!今天我們要來聊聊「狀態模式 (State)」。如果你把物件想像成一個人,那麼狀態模式就是用來管理這個人的 「心情」轉變。一個物件在不同的狀態下可能會有不同的行為,就好像我們在不同的心情下反應也不同,對吧?
狀態模式允許一個物件在其內部狀態改變時改變其行為。物件似乎改變了它的類別。換句話說,狀態模式能幫助你避免過多的 if-else
或 switch
語句。
想像你正在開發一個簡單的音樂播放器,它有三種狀態:播放
、暫停
和停止
。每當用戶按下按鈕,播放器的狀態就會改變。
package main
import "fmt"
// State 介面定義了處理狀態的方法。
type State interface {
Handle(context *MusicPlayerContext)
}
// PlayState 表示播放狀態。
type PlayState struct{}
func (p *PlayState) Handle(context *MusicPlayerContext) {
fmt.Println("正在播放音樂")
context.SetState(&PauseState{})
}
// PauseState 表示暫停狀態。
type PauseState struct{}
func (p *PauseState) Handle(context *MusicPlayerContext) {
fmt.Println("音樂已暫停")
context.SetState(&StopState{})
}
// StopState 表示停止狀態。
type StopState struct{}
func (s *StopState) Handle(context *MusicPlayerContext) {
fmt.Println("音樂已停止")
context.SetState(&PlayState{})
}
// MusicPlayerContext 包含當前的狀態。
type MusicPlayerContext struct {
state State
}
func (m *MusicPlayerContext) SetState(state State) {
m.state = state
}
func (m *MusicPlayerContext) PressPlayButton() {
m.state.Handle(m)
}
func main() {
player := &MusicPlayerContext{state: &StopState{}}
player.PressPlayButton() // 音樂已停止
player.PressPlayButton() // 正在播放音樂
player.PressPlayButton() // 音樂已暫停
}
透過上述例子,你可以看到播放器是如何在不同狀態之間轉換的。
如果你正在開發一個遊戲,角色可能會有:正常
、受傷
和死亡
等狀態。在受傷
狀態下,角色的移動速度可能會減慢;在死亡
狀態下,角色可能不能移動。通過使用狀態模式,你可以輕鬆管理角色在不同狀態下的行為。
package main
import "fmt"
// CharacterState 是一個介面,定義了不同角色狀態的 Move 方法。
type CharacterState interface {
Move()
}
// HealthyState 表示角色健康狀態。
type HealthyState struct{}
func (h *HealthyState) Move() {
fmt.Println("角色快速移動!") // 角色快速移動!
}
// InjuredState 表示角色受傷狀態。
type InjuredState struct{}
func (i *InjuredState) Move() {
fmt.Println("角色移動得有點慢...") // 角色移動得有點慢...
}
// DeadState 表示角色死亡狀態。
type DeadState struct{}
func (d *DeadState) Move() {
fmt.Println("角色不能移動,他已經...RIP。") // 角色不能移動,他已經...RIP。
}
// GameCharacter 表示帶有特定狀態的遊戲角色。
type GameCharacter struct {
state CharacterState
}
func (g *GameCharacter) SetState(state CharacterState) {
g.state = state
}
func (g *GameCharacter) Move() {
g.state.Move()
}
func main() {
hero := &GameCharacter{state: &HealthyState{}}
hero.Move() // 角色快速移動!
hero.SetState(&InjuredState{})
hero.Move() // 角色移動得有點慢...
hero.SetState(&DeadState{})
hero.Move() // 角色不能移動,他已經...RIP。
}
從上面的例子你可以看到,每當角色狀態改變,他的移動方式也隨之改變。這不就像遊戲裡的角色真的受傷或死掉嗎?
狀態模式不只讓代碼更整潔,還能讓你更容易模擬現實生活的情境。它幫助我們整理代碼,避免過多的條件判斷,並保持我們的代碼整潔。所以,下次當你的物件有很多可能的「狀態」時,你知道該怎麼辦了吧!😆