Golang - Design Pattern #8: 狀態模式 (State)

閱讀時間約 6 分鐘
raw-image
狀態模式:就像你的心情變化!

大家好!今天我們要來聊聊「狀態模式 (State)」。如果你把物件想像成一個人,那麼狀態模式就是用來管理這個人的 「心情」轉變。一個物件在不同的狀態下可能會有不同的行為,就好像我們在不同的心情下反應也不同,對吧?


深入探索

狀態模式允許一個物件在其內部狀態改變時改變其行為。物件似乎改變了它的類別。換句話說,狀態模式能幫助你避免過多的 if-elseswitch 語句。


Go Go Go

🎵 音樂播放器

想像你正在開發一個簡單的音樂播放器,它有三種狀態:播放暫停停止。每當用戶按下按鈕,播放器的狀態就會改變。
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。
}

從上面的例子你可以看到,每當角色狀態改變,他的移動方式也隨之改變。這不就像遊戲裡的角色真的受傷或死掉嗎?


總結一下

狀態模式不只讓代碼更整潔,還能讓你更容易模擬現實生活的情境。它幫助我們整理代碼,避免過多的條件判斷,並保持我們的代碼整潔。所以,下次當你的物件有很多可能的「狀態」時,你知道該怎麼辦了吧!😆


30會員
193內容數
歡迎來到【代碼的詩情】:探索程式語言之美 系列,這是一場優雅的程式之旅,透過詩歌的抒發,尋找不同程式語言的美感和精髓。 在這個系列中,我們將透過文字的韻律,深入探索多種程式語言的核心概念和語法,以及它們獨特的應用和技巧。每一篇詩歌都是一個故事,每一段代碼都是一句詩句,讓代碼的旋律和詩情在其中相互交織。
留言0
查看全部
發表第一個留言支持創作者!
你可能也想看
創作者要怎麼好好休息 + 避免工作過量?《黑貓創作報#4》午安,最近累不累? 這篇不是虛假的關心。而是《黑貓創作報》發行以來可能最重要的一篇。 是的,我們這篇講怎麼補充能量,也就是怎麼休息。
Thumbnail
avatar
黑貓老師
2024-06-29
防曬產品係數測試報告彙整(2024年)從2014年起,自己對於市售防曬產品的效能產生了濃厚的興趣。因為當時候發現不少產品的防曬係數其實標示是有問題的,像是原本應該是人體測試的SPF與PA數值,實際上沒有做,只用機器測試的數據來充當,但這兩者卻有很大的差異。像是防曬係數其實有強度、廣度與平均度三個面向需要一起判斷,但多數廠商並沒有完整標示
Thumbnail
avatar
邱品齊皮膚科醫師
2023-04-27
Golang 的資料型別一覽👨‍💻簡介 Go 語言有各種資料型別,分為基本型別和複合型別。基本型別包括: 整數、浮點數、布林值、字串 複合型別包括: 陣列、片段、結構、函式、對映、通道、介面 等。 整數型別 整數型別有許多種,像是 int8、int16、int32、int64。我們可以依據實際需求選擇。
Thumbnail
avatar
wang alan
2023-08-17
韓國SONO CALM GOYANG HOTEL跟團住在號稱5星級飯店,SONO CALM GOYANG HOTEL 出發前在網路上找不到相關資料,google附近的地圖失真,於是來發一篇文 沒拍房間內部,房間還蠻大的,兩張單人床中間兩旁都有空間可以走動,開放式衣架,備品有小瓶沐浴乳、洗髮精、潤髮乳,都是濃濃的薄荷味,如果不能接受的話,最好自
Thumbnail
avatar
lunar
2023-07-13
Design | JPEG、PNG、PDF 差異與介紹這篇文章將會講述常用圖檔的檔案格式差異、比較和應用。
Thumbnail
avatar
瓶裝雪
2022-11-16
Designer | 個人專案(Side Project)Side Project 是打破傳說魔咒的解咒法,對於新鮮人來說,要找工作大多都要求工作經驗,然而這就跟打副本需要至少兩次刷副本的經驗一樣,若在團隊中沒有熟人,永遠會卡在等級一。
Thumbnail
avatar
瓶裝雪
2022-07-13
Singleton design patternSingleton design pattern
Thumbnail
avatar
Vic Lin
2020-08-20
Web Design Hong Kong - MiracleWeb design Agency Miracle Hong Kong understands the importance of a website design that works and converts your target audience into customers. We hav
avatar
Marlon Francis
2020-03-18
Design about food X 消化 Digest|篆刻創作特展 從服務生小姐到藝術家,從飲食色彩活動到個人篆刻特展,我很榮幸身邊有一位跟我一樣關注飲食與人,熱愛自我探索、享受實驗驗證過程的好朋友 -蔡大暇
Thumbnail
avatar
Amber 詹慧珍
2020-02-20
建立 Golang http web server建議先看過Golang 入門這篇再閱讀這篇! 使用Go官方提供的net/http library就能建立http web伺服器囉!
Thumbnail
avatar
Vic Lin
2019-11-16
Golang 入門Golang 入門
Thumbnail
avatar
Vic Lin
2019-11-09
Golang RegExp Notes遙想當年初探 Regular Expression,腦袋紮紮實實地被凌虐了一番,同時十分敬佩把正規表示式寫的簡潔有力又精確無誤的神人。最近學校在上編譯器課程,估計近期內便會接觸到不少 RegExp 的技巧,於是就來寫篇筆記吧~
Thumbnail
avatar
Rain Wu
2019-03-17