<\/span><\/h2>\n\n\n\n The below table represents the mapping from the UML diagram actors to actual implementation actors in code. <\/p>\n\n\n\nContext<\/td> vendingMachine.go<\/td><\/tr> State Interface<\/td> state.go<\/td><\/tr> Concrete State 1<\/td> noItemState.go<\/td><\/tr> Concrete State 2<\/td> hasItemState.go<\/td><\/tr> Concrete State 3<\/td> itemRequestedState.go<\/td><\/tr> Concrete State 4<\/td> hasMoneyState.go<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<\/span>Explanation:<\/strong><\/span><\/h2>\n\n\n\nWe have an interface “State” which defines signatures of functions that represents action in the context of Vending Machine. Below are the actions function signaturesaddItem(int) error<\/li> requestItem() error<\/li> insertMoney(money int) error<\/li> dispenseItem() error<\/li><\/ol><\/li> Each of the concrete state implementations implements all 4 above function and either move to another state on these actions or gives some response.<\/li> Each of the concrete state also embeds a pointer to current Vending Machine object so that state transition can happen on that object.<\/li><\/ul>\n\n\n\nNow lets look at code <\/p>\n\n\n\n
<\/span>Practical Example:<\/strong><\/span><\/h2>\n\n\n\nvendingMachine.go<\/strong><\/p>\n\n\n\npackage main\n\nimport \"fmt\"\n\ntype vendingMachine struct {\n hasItem state\n itemRequested state\n hasMoney state\n noItem state\n\n currentState state\n\n itemCount int\n itemPrice int\n}\n\nfunc newVendingMachine(itemCount, itemPrice int) *vendingMachine {\n v := &vendingMachine{\n itemCount: itemCount,\n itemPrice: itemPrice,\n }\n hasItemState := &hasItemState{\n vendingMachine: v,\n }\n itemRequestedState := &itemRequestedState{\n vendingMachine: v,\n }\n hasMoneyState := &hasMoneyState{\n vendingMachine: v,\n }\n noItemState := &noItemState{\n vendingMachine: v,\n }\n\n v.setState(hasItemState)\n v.hasItem = hasItemState\n v.itemRequested = itemRequestedState\n v.hasMoney = hasMoneyState\n v.noItem = noItemState\n return v\n}\n\nfunc (v *vendingMachine) requestItem() error {\n return v.currentState.requestItem()\n}\n\nfunc (v *vendingMachine) addItem(count int) error {\n return v.currentState.addItem(count)\n}\n\nfunc (v *vendingMachine) insertMoney(money int) error {\n return v.currentState.insertMoney(money)\n}\n\nfunc (v *vendingMachine) dispenseItem() error {\n return v.currentState.dispenseItem()\n}\n\nfunc (v *vendingMachine) setState(s state) {\n v.currentState = s\n}\n\nfunc (v *vendingMachine) incrementItemCount(count int) {\n fmt.Printf(\"Adding %d items\\n\", count)\n v.itemCount = v.itemCount + count\n}<\/code><\/pre>\n\n\n\nstate.go<\/strong><\/p>\n\n\n\npackage main\n\ntype state interface {\n addItem(int) error\n requestItem() error\n insertMoney(money int) error\n dispenseItem() error\n}<\/code><\/pre>\n\n\n\nnoItemState.go<\/strong><\/p>\n\n\n\npackage main\n\nimport \"fmt\"\n\ntype noItemState struct {\n vendingMachine *vendingMachine\n}\n\nfunc (i *noItemState) requestItem() error {\n return fmt.Errorf(\"Item out of stock\")\n}\n\nfunc (i *noItemState) addItem(count int) error {\n i.vendingMachine.incrementItemCount(count)\n i.vendingMachine.setState(i.vendingMachine.hasItem)\n return nil\n}\n\nfunc (i *noItemState) insertMoney(money int) error {\n return fmt.Errorf(\"Item out of stock\")\n}\nfunc (i *noItemState) dispenseItem() error {\n return fmt.Errorf(\"Item out of stock\")\n}<\/code><\/pre>\n\n\n\nhasItemState.go<\/strong><\/p>\n\n\n\npackage main\n\nimport \"fmt\"\n\ntype hasItemState struct {\n vendingMachine *vendingMachine\n}\n\nfunc (i *hasItemState) requestItem() error {\n if i.vendingMachine.itemCount == 0 {\n i.vendingMachine.setState(i.vendingMachine.noItem)\n return fmt.Errorf(\"No item present\")\n }\n fmt.Printf(\"Item requestd\\n\")\n i.vendingMachine.setState(i.vendingMachine.itemRequested)\n return nil\n}\n\nfunc (i *hasItemState) addItem(count int) error {\n fmt.Printf(\"%d items added\\n\", count)\n i.vendingMachine.incrementItemCount(count)\n return nil\n}\n\nfunc (i *hasItemState) insertMoney(money int) error {\n return fmt.Errorf(\"Please select item first\")\n}\nfunc (i *hasItemState) dispenseItem() error {\n return fmt.Errorf(\"Please select item first\")\n}<\/code><\/pre>\n\n\n\nitemRequestedState.go<\/strong><\/p>\n\n\n\npackage main\n\nimport \"fmt\"\n\ntype itemRequestedState struct {\n vendingMachine *vendingMachine\n}\n\nfunc (i *itemRequestedState) requestItem() error {\n return fmt.Errorf(\"Item already requested\")\n}\n\nfunc (i *itemRequestedState) addItem(count int) error {\n return fmt.Errorf(\"Item Dispense in progress\")\n}\n\nfunc (i *itemRequestedState) insertMoney(money int) error {\n if money < i.vendingMachine.itemPrice {\n fmt.Errorf(\"Inserted money is less. Please insert %d\", i.vendingMachine.itemPrice)\n }\n fmt.Println(\"Money entered is ok\")\n i.vendingMachine.setState(i.vendingMachine.hasMoney)\n return nil\n}\n\nfunc (i *itemRequestedState) dispenseItem() error {\n return fmt.Errorf(\"Please insert money first\")\n}<\/code><\/pre>\n\n\n\nhasMoneyState.go<\/strong><\/p>\n\n\n\npackage main\n\nimport \"fmt\"\n\ntype hasMoneyState struct {\n vendingMachine *vendingMachine\n}\n\nfunc (i *hasMoneyState) requestItem() error {\n return fmt.Errorf(\"Item dispense in progress\")\n}\n\nfunc (i *hasMoneyState) addItem(count int) error {\n return fmt.Errorf(\"Item dispense in progress\")\n}\n\nfunc (i *hasMoneyState) insertMoney(money int) error {\n return fmt.Errorf(\"Item out of stock\")\n}\n\nfunc (i *hasMoneyState) dispenseItem() error {\n fmt.Println(\"Dispensing Item\")\n i.vendingMachine.itemCount = i.vendingMachine.itemCount - 1\n if i.vendingMachine.itemCount == 0 {\n i.vendingMachine.setState(i.vendingMachine.noItem)\n } else {\n i.vendingMachine.setState(i.vendingMachine.hasItem)\n }\n return nil\n}<\/code><\/pre>\n\n\n\nmain.go<\/strong><\/p>\n\n\n\npackage main\n\nimport (\n \"fmt\"\n \"log\"\n)\n\nfunc main() {\n vendingMachine := newVendingMachine(1, 10)\n err := vendingMachine.requestItem()\n if err != nil {\n log.Fatalf(err.Error())\n }\n err = vendingMachine.insertMoney(10)\n if err != nil {\n log.Fatalf(err.Error())\n }\n err = vendingMachine.dispenseItem()\n if err != nil {\n log.Fatalf(err.Error())\n }\n\n fmt.Println()\n err = vendingMachine.addItem(2)\n if err != nil {\n log.Fatalf(err.Error())\n }\n\n fmt.Println()\n\n err = vendingMachine.requestItem()\n if err != nil {\n log.Fatalf(err.Error())\n }\n\n err = vendingMachine.insertMoney(10)\n if err != nil {\n log.Fatalf(err.Error())\n }\n\n err = vendingMachine.dispenseItem()\n if err != nil {\n log.Fatalf(err.Error())\n }\n}<\/code><\/pre>\n\n\n\nOutput:<\/strong><\/p>\n\n\n\nItem requestd\nMoney entered is ok\nDispensing Item\n\nAdding 2 items\n\nItem requestd\nMoney entered is ok\nDispensing Item<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"Note: Interested in understanding how all other design patterns can be implemented in GO. Please see this full reference – All Design Patterns in Go (Golang) Table of Contents Definition:When To UseUML…<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spay_email":"","footnotes":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false},"categories":[1],"tags":[26,30,3,4,31,33,32],"class_list":["post-259","post","type-post","status-publish","format-standard","hentry","category-tech","tag-design","tag-designpattern","tag-go","tag-golang","tag-patter","tag-state","tag-state-design-pattern"],"yoast_head":"\n
State Design pattern in Go - Welcome To Golang By Example<\/title>\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n\t \n\t \n\t \n