Go設(shè)計(jì)模式之狀態(tài)模式講解和代碼示例
Go 狀態(tài)模式講解和代碼示例
概念示例
讓我們?cè)谝慌_(tái)自動(dòng)售貨機(jī)上使用狀態(tài)設(shè)計(jì)模式。 為簡(jiǎn)單起見(jiàn), 讓我們假設(shè)自動(dòng)售貨機(jī)僅會(huì)銷(xiāo)售一種類(lèi)型的商品。 同時(shí), 依然為了簡(jiǎn)單起見(jiàn), 我們假設(shè)自動(dòng)售貨機(jī)可處于 4 種不同的狀態(tài)中:
- 有商品 (hasItem)
- 無(wú)商品 (noItem)
- 商品已請(qǐng)求 (itemRequested)
- 收到紙幣 (hasMoney)
同時(shí), 自動(dòng)售貨機(jī)也會(huì)有不同的操作。 再一次的, 為了簡(jiǎn)單起見(jiàn), 我們假設(shè)其只會(huì)執(zhí)行 4 種操作:
- 選擇商品
- 添加商品
- 插入紙幣
- 提供商品
當(dāng)對(duì)象可以處于許多不同的狀態(tài)中時(shí)應(yīng)使用狀態(tài)設(shè)計(jì)模式, 同時(shí)根據(jù)傳入請(qǐng)求的不同, 對(duì)象需要變更其當(dāng)前狀態(tài)。
在我們的例子中, 自動(dòng)售貨機(jī)可以有多種不同的狀態(tài), 同時(shí)會(huì)在這些狀態(tài)之間持續(xù)不斷地互相轉(zhuǎn)換。 我們假設(shè)自動(dòng)售貨機(jī)處于 商品已請(qǐng)求
狀態(tài)中。 在 “插入紙幣” 的操作發(fā)生后, 機(jī)器將自動(dòng)轉(zhuǎn)換至 收到紙幣
狀態(tài)。
根據(jù)其當(dāng)前狀態(tài), 機(jī)器可就相同請(qǐng)求采取不同的行為。 例如, 如果用戶(hù)想要購(gòu)買(mǎi)一件商品, 機(jī)器將在 有商品
狀態(tài)時(shí)繼續(xù)操作, 而在 無(wú)商品
狀態(tài)時(shí)拒絕操作。
自動(dòng)售貨機(jī)的代碼不會(huì)被這一邏輯污染; 所有依賴(lài)于狀態(tài)的代碼都存在于各自的狀態(tài)實(shí)現(xiàn)中。
vendingMachine.go: 背景
package main import "fmt" type VendingMachine struct { hasItem State itemRequested State hasMoney State noItem State currentState State // 當(dāng)前狀態(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" // 無(wú)貨狀態(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: 客戶(hù)端代碼
package main import ( "fmt" "log" ) func main() { vendingMachine := newVendingMachine(1, 10) // 獲取一個(gè)商品 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設(shè)計(jì)模式之狀態(tài)模式講解和代碼示例的文章就介紹到這了,更多相關(guān)Go狀態(tài)模式內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Golang利用casbin實(shí)現(xiàn)權(quán)限驗(yàn)證詳解
Casbin是一個(gè)強(qiáng)大的、高效的開(kāi)源訪問(wèn)控制框架,其權(quán)限管理機(jī)制支持多種訪問(wèn)控制模型,Casbin只負(fù)責(zé)訪問(wèn)控制。本文將利用casbin實(shí)現(xiàn)權(quán)限驗(yàn)證功能,需要的可以參考一下2023-02-02Go項(xiàng)目實(shí)現(xiàn)優(yōu)雅關(guān)機(jī)與平滑重啟功能
無(wú)論是優(yōu)雅關(guān)機(jī)還是優(yōu)雅重啟歸根結(jié)底都是通過(guò)監(jiān)聽(tīng)特定系統(tǒng)信號(hào),然后執(zhí)行一定的邏輯處理保障當(dāng)前系統(tǒng)正在處理的請(qǐng)求被正常處理后再關(guān)閉當(dāng)前進(jìn)程,這篇文章主要介紹了Go實(shí)現(xiàn)優(yōu)雅關(guān)機(jī)與平滑重啟 ,需要的朋友可以參考下2022-10-10GO語(yǔ)言創(chuàng)建錢(qián)包并遍歷錢(qián)包(wallet)的實(shí)現(xiàn)代碼
比特幣錢(qián)包實(shí)際上是一個(gè)密鑰對(duì),當(dāng)你安裝 一個(gè)錢(qián)包應(yīng)用,或者是使用一個(gè)比特幣客戶(hù)端來(lái)生成一個(gè)新地址是,他就會(huì)為你生成一個(gè)密鑰對(duì),今天通過(guò)本文給大家分享go語(yǔ)言遍歷錢(qián)包的相關(guān)知識(shí),一起看看吧2021-05-05Go實(shí)現(xiàn)用戶(hù)每日限額的方法(例一天只能領(lǐng)三次福利)
這篇文章主要介紹了Go實(shí)現(xiàn)用戶(hù)每日限額的方法(例一天只能領(lǐng)三次福利)2022-01-01Go實(shí)現(xiàn)替換(覆蓋)文件某一行內(nèi)容的示例代碼
本文主要介紹了Go實(shí)現(xiàn)替換(覆蓋)文件某一行內(nèi)容的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07