Go設計模式之狀態(tài)模式講解和代碼示例
Go 狀態(tài)模式講解和代碼示例
概念示例
讓我們在一臺自動售貨機上使用狀態(tài)設計模式。 為簡單起見, 讓我們假設自動售貨機僅會銷售一種類型的商品。 同時, 依然為了簡單起見, 我們假設自動售貨機可處于 4 種不同的狀態(tài)中:
- 有商品 (hasItem)
- 無商品 (noItem)
- 商品已請求 (itemRequested)
- 收到紙幣 (hasMoney)
同時, 自動售貨機也會有不同的操作。 再一次的, 為了簡單起見, 我們假設其只會執(zhí)行 4 種操作:
- 選擇商品
- 添加商品
- 插入紙幣
- 提供商品
當對象可以處于許多不同的狀態(tài)中時應使用狀態(tài)設計模式, 同時根據(jù)傳入請求的不同, 對象需要變更其當前狀態(tài)。
在我們的例子中, 自動售貨機可以有多種不同的狀態(tài), 同時會在這些狀態(tài)之間持續(xù)不斷地互相轉(zhuǎn)換。 我們假設自動售貨機處于 商品已請求
狀態(tài)中。 在 “插入紙幣” 的操作發(fā)生后, 機器將自動轉(zhuǎn)換至 收到紙幣
狀態(tài)。
根據(jù)其當前狀態(tài), 機器可就相同請求采取不同的行為。 例如, 如果用戶想要購買一件商品, 機器將在 有商品
狀態(tài)時繼續(xù)操作, 而在 無商品
狀態(tài)時拒絕操作。
自動售貨機的代碼不會被這一邏輯污染; 所有依賴于狀態(tài)的代碼都存在于各自的狀態(tài)實現(xiàn)中。
vendingMachine.go: 背景
package main import "fmt" type VendingMachine struct { hasItem State itemRequested State hasMoney State noItem State currentState State // 當前狀態(tài) itemCount int itemPrice int } func newVendingMachine(itemCount, itemPrice int) *VendingMachine { v := &VendingMachine{ itemCount: itemCount, itemPrice: itemPrice, } hasItemState := &HasItemState{vendingMachine: v} itemRequestState := &ItemRequestedState{vendingMachine: v} hasMoneyState := &HasMoneyState{vendingMachine: v} noItemState := &NoItemState{vendingMachine: v} v.setState(hasItemState) v.hasItem = hasItemState v.itemRequested = itemRequestState v.hasMoney = hasMoneyState v.noItem = noItemState return v } func (v *VendingMachine) requestItem() error { return v.currentState.requestItem() } func (v *VendingMachine) addItem(count int) error { return v.currentState.addItem(count) } func (v *VendingMachine) insertMoney(money int) error { return v.currentState.insertMoney(money) } func (v *VendingMachine) dispenseItem() error { return v.currentState.dispenseItem() } func (v *VendingMachine) setState(s State) { v.currentState = s } func (v *VendingMachine) incrementItemCount(count int) { fmt.Printf("Adding %d items \n", count) v.itemCount = count + v.itemCount }
state.go: 狀態(tài)接口
package main type State interface { addItem(int) error requestItem() error insertMoney(money int) error dispenseItem() error }
noItemState.go: 具體狀態(tài)
package main import "fmt" // 無貨狀態(tài) type NoItemState struct { vendingMachine *VendingMachine } func (i *NoItemState) requestItem() error { return fmt.Errorf("Item out of stock") } func (i *NoItemState) addItem(count int) error { i.vendingMachine.incrementItemCount(count) i.vendingMachine.setState(i.vendingMachine.hasItem) return nil } func (i *NoItemState) insertMoney(money int) error { return fmt.Errorf("Item out of stock") } func (i *NoItemState) dispenseItem() error { return fmt.Errorf("Item out of stock") }
hasItemState.go: 具體狀態(tài)
package main import "fmt" type HasItemState struct { vendingMachine *VendingMachine } func (i *HasItemState) requestItem() error { if i.vendingMachine.itemCount == 0 { i.vendingMachine.setState(i.vendingMachine.noItem) return fmt.Errorf("No item present") } fmt.Printf("Item requested \n") i.vendingMachine.setState(i.vendingMachine.itemRequested) return nil } func (i *HasItemState) addItem(count int) error { fmt.Printf("%d item added", count) i.vendingMachine.incrementItemCount(count) return nil } func (i *HasItemState) insertMoney(money int) error { return fmt.Errorf("please select item first") } func (i *HasItemState) dispenseItem() error { return fmt.Errorf("Please select item first") }
itemRequestedState.go: 具體狀態(tài)
package main import "fmt" type ItemRequestedState struct { vendingMachine *VendingMachine } func (i *ItemRequestedState) requestItem() error { return fmt.Errorf("Item already requested") } func (i *ItemRequestedState) addItem(count int) error { return fmt.Errorf("Item Dispense in progress") } func (i *ItemRequestedState) insertMoney(money int) error { if money < i.vendingMachine.itemPrice { return fmt.Errorf("Inserted money is less. Please insert %d", i.vendingMachine.itemPrice) } fmt.Println("Money entered is ok") i.vendingMachine.setState(i.vendingMachine.hasMoney) return nil } func (i *ItemRequestedState) dispenseItem() error { return fmt.Errorf("Please insert money first") }
hasMoneyState.go: 具體狀態(tài)
package main import "fmt" type HasMoneyState struct { vendingMachine *VendingMachine } func (i *HasMoneyState) requestItem() error { return fmt.Errorf("Item dispense in progress") } func (i *HasMoneyState) addItem(count int) error { return fmt.Errorf("Item dispense in progress") } func (i *HasMoneyState) insertMoney(money int) error { return fmt.Errorf("item out of stock") } func (i *HasMoneyState) dispenseItem() error { fmt.Println("Dispensing Item") i.vendingMachine.itemCount = i.vendingMachine.itemCount - 1 if i.vendingMachine.itemCount == 0 { i.vendingMachine.setState(i.vendingMachine.noItem) } else { i.vendingMachine.setState(i.vendingMachine.hasItem) } return nil }
main.go: 客戶端代碼
package main import ( "fmt" "log" ) func main() { vendingMachine := newVendingMachine(1, 10) // 獲取一個商品 if err := vendingMachine.requestItem(); err != nil { log.Fatalf(err.Error()) } if err := vendingMachine.insertMoney(10); err != nil { log.Fatal(err.Error()) } if err := vendingMachine.dispenseItem(); err != nil { log.Fatal(err.Error()) } fmt.Println("================") if err := vendingMachine.addItem(2); err != nil { log.Fatal(err.Error()) } fmt.Println() if err := vendingMachine.requestItem(); err != nil { log.Fatal(err.Error()) } if err := vendingMachine.insertMoney(10); err != nil { log.Fatal(err.Error()) } if err := vendingMachine.dispenseItem(); err != nil { log.Fatal(err.Error()) } }
output.txt: 執(zhí)行結(jié)果
Item requested
Money entered is ok
Dispensing Item
================
Adding 2 itemsItem requested
Money entered is ok
Dispensing Item
到此這篇關(guān)于Go設計模式之狀態(tài)模式講解和代碼示例的文章就介紹到這了,更多相關(guān)Go狀態(tài)模式內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Golang利用casbin實現(xiàn)權(quán)限驗證詳解
Casbin是一個強大的、高效的開源訪問控制框架,其權(quán)限管理機制支持多種訪問控制模型,Casbin只負責訪問控制。本文將利用casbin實現(xiàn)權(quán)限驗證功能,需要的可以參考一下2023-02-02Go項目實現(xiàn)優(yōu)雅關(guān)機與平滑重啟功能
無論是優(yōu)雅關(guān)機還是優(yōu)雅重啟歸根結(jié)底都是通過監(jiān)聽特定系統(tǒng)信號,然后執(zhí)行一定的邏輯處理保障當前系統(tǒng)正在處理的請求被正常處理后再關(guān)閉當前進程,這篇文章主要介紹了Go實現(xiàn)優(yōu)雅關(guān)機與平滑重啟 ,需要的朋友可以參考下2022-10-10GO語言創(chuàng)建錢包并遍歷錢包(wallet)的實現(xiàn)代碼
比特幣錢包實際上是一個密鑰對,當你安裝 一個錢包應用,或者是使用一個比特幣客戶端來生成一個新地址是,他就會為你生成一個密鑰對,今天通過本文給大家分享go語言遍歷錢包的相關(guān)知識,一起看看吧2021-05-05Go實現(xiàn)用戶每日限額的方法(例一天只能領(lǐng)三次福利)
這篇文章主要介紹了Go實現(xiàn)用戶每日限額的方法(例一天只能領(lǐng)三次福利)2022-01-01Go實現(xiàn)替換(覆蓋)文件某一行內(nèi)容的示例代碼
本文主要介紹了Go實現(xiàn)替換(覆蓋)文件某一行內(nèi)容的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-07-07