HouseOfFlower is hosting a betting sale. People can use a blue diamond to start a bet. If they win the bet, they’ll get one flower. The “FlowerHouseContext” is trying to keep a record of the business by using the four states: NoDiamond, HasDiamond, Sold, Soldout.
The state pattern is used to alter the behaviour of an object as its internal state changes. The pattern allows the class for an object to apparently change at run-time. From
class FlowerHouseContext: CustomStringConvertible {
// need a special inital state, but really no use here
private var state: State = NoDiamondState()
private var numberOfFlowers: Int = 5
private var gotDiamond = false
private var wonBet = false
private var totalReceivedDiamonds: Int = 0
var description:String { return "--FlowerHouse: total flowers: \(numberOfFlowers)@, total diamonds:\(totalReceivedDiamonds)#"
}
func receiveDiamond(){
if numberOfFlowers <= 0 {
state = SoldOutState()
state.getFlower(self)
} else {
state.giveDiamond(self)
state = HasDiamondState()
gotDiamond = true
totalReceivedDiamonds++
}
}
func startBet(){
if !gotDiamond {
state.willGiveDiamond()
} else {
if arc4random_uniform(2) == 1 {
wonBet = true
} else {
print("You lose the bet, no flowers")
state = NoDiamondState()
gotDiamond = false
}
}
}
func giveFlower(){
if gotDiamond && wonBet {
numberOfFlowers--
state = SoldState()
state.getFlower(self)
print(description)
state = NoDiamondState()
gotDiamond = false
wonBet = false
} else {
if let _ = state as? HasDiamondState {
print("You'll need to start a bet to get a flower")
} else {
print(state.description)
}
}
}
}
//: the context Parameter is not necessary here, but maybe for future usage.
protocol State: CustomStringConvertible {
func willGiveDiamond()
func giveDiamond(context: FlowerHouseContext)
func startBet(context: FlowerHouseContext)
func getFlower(context: FlowerHouseContext)
}
class NoDiamondState:State {
var description:String {return "No diamond yet. Need to give one"}
func willGiveDiamond(){
print("You need to give a diamond to start the bet")
}
func giveDiamond(context: FlowerHouseContext) {
print("You are giving a diamond")
}
func startBet(context: FlowerHouseContext) {
print("Can't start bet without a diamond")
}
func getFlower(context: FlowerHouseContext) {
print("Can't get flower without a diamond")
}
}
class HasDiamondState:State {
var description:String {return "You gave one diamond. Will start the bet"}
func willGiveDiamond(){
print("You already gave a diamond")
}
func giveDiamond(context: FlowerHouseContext) {
print("You already gave a diamond")
}
func startBet(context: FlowerHouseContext) {
print("The best is starting")
}
func getFlower(context: FlowerHouseContext) {
print("No bet, no flower")
}
}
class SoldState:State {
var description: String {return "You won the bet, will give you a flower"}
func willGiveDiamond(){
print("You already gave a diamond")
}
func giveDiamond(context: FlowerHouseContext) {
print("You already gave a diamond")
}
func startBet(context: FlowerHouseContext) {
print("The bet is already over")
}
func getFlower(context: FlowerHouseContext) {
print("you won the bed and you get one flower")
}
}
class SoldOutState:State {
var description:String {return "Sold out, come back later"}
func willGiveDiamond(){
print("Sold out, come back later")
}
func giveDiamond(context: FlowerHouseContext) {
print("Sold out, come back later")
}
func startBet(context: FlowerHouseContext) {
print("Sold out, come back later")
}
func getFlower(context: FlowerHouseContext) {
print("Sold out, come back later")
}
}
//:Testing
let context = FlowerHouseContext()
print(context)
context.receiveDiamond()
context.startBet()
context.giveFlower()
print("\n")
context.startBet()
context.receiveDiamond()
context.startBet()
context.giveFlower()
print("\n")
context.startBet()
context.giveFlower()
print("\n")
context.receiveDiamond()
context.giveFlower()