Skip to content

Instantly share code, notes, and snippets.

@dodalovic
Last active July 8, 2023 21:28
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dodalovic/59ad8208461a96e38662d2fdf7786fdc to your computer and use it in GitHub Desktop.
Save dodalovic/59ad8208461a96e38662d2fdf7786fdc to your computer and use it in GitHub Desktop.
State pattern implemented in kotlin
package patterns.head_first
class CoffeeMachine {
var state: CoffeeMachineState
val MAX_BEANS_QUANTITY = 100
val MAX_WATER_QUANTITY = 100
var beansQuantity = 0
var waterQuantity = 0
val offState = Off(this)
val noIngredients = NoIngredients(this)
val ready = Ready(this)
init {
state = offState
}
fun turnOn() = state.turnOn()
fun fillInBeans(quantity: Int) = state.fillInBeans(quantity)
fun fillInWater(quantity: Int) = state.fillInWater(quantity)
fun makeCoffee() = state.makeCoffee()
fun turnOff() = state.turnOff()
override fun toString(): String {
return """COFFEE MACHINE → ${state::class.simpleName}
| water quantity : $waterQuantity
| beans quantity : $beansQuantity
|""".trimMargin()
}
}
abstract class CoffeeMachineState(val coffeeMachine: CoffeeMachine) {
open fun makeCoffee(): Unit = throw UnsupportedOperationException("Operation not supported")
open fun fillInBeans(quantity: Int): Unit = throw UnsupportedOperationException("Operation not supported")
open fun fillInWater(quantity: Int): Unit = throw UnsupportedOperationException("Operation not supported")
open fun turnOn(): Unit = throw UnsupportedOperationException("Operation not supported")
fun turnOff(): Unit {
coffeeMachine.state = coffeeMachine.offState
}
}
class Off(coffeeMachine: CoffeeMachine) : CoffeeMachineState(coffeeMachine) {
override fun turnOn() {
coffeeMachine.state = coffeeMachine.noIngredients
println("Coffee machine turned on")
}
}
class NoIngredients(coffeeMachine: CoffeeMachine) : CoffeeMachineState(coffeeMachine) {
override fun fillInBeans(quantity: Int) {
if ((coffeeMachine.beansQuantity + quantity) <= coffeeMachine.MAX_BEANS_QUANTITY) {
coffeeMachine.beansQuantity += quantity
println("Beans filled in")
if (coffeeMachine.waterQuantity > 0) {
coffeeMachine.state = coffeeMachine.ready
}
}
}
override fun fillInWater(quantity: Int) {
if ((coffeeMachine.waterQuantity + quantity) <= coffeeMachine.MAX_WATER_QUANTITY) {
coffeeMachine.waterQuantity += quantity
println("Water filled in")
if (coffeeMachine.beansQuantity > 0) {
coffeeMachine.state = coffeeMachine.ready
}
}
}
}
class Ready(coffeeMachine: CoffeeMachine) : CoffeeMachineState(coffeeMachine) {
override fun makeCoffee() {
coffeeMachine.beansQuantity--
coffeeMachine.waterQuantity--
println("Making coffee ... DONE")
if (coffeeMachine.beansQuantity == 0 || coffeeMachine.waterQuantity == 0) {
coffeeMachine.state = coffeeMachine.noIngredients
}
}
}
fun main(args: Array<String>) {
val coffeeMachine = CoffeeMachine()
coffeeMachine.turnOn()
println(coffeeMachine)
coffeeMachine.fillInBeans(2)
println(coffeeMachine)
coffeeMachine.fillInWater(2)
println(coffeeMachine)
coffeeMachine.makeCoffee()
println(coffeeMachine)
coffeeMachine.makeCoffee()
println(coffeeMachine)
coffeeMachine.turnOff()
println(coffeeMachine)
}
Coffee machine turned on
COFFEE MACHINE → NoIngredients
water quantity : 0
beans quantity : 0
Beans filled in
COFFEE MACHINE → NoIngredients
water quantity : 0
beans quantity : 2
Water filled in
COFFEE MACHINE → Ready
water quantity : 2
beans quantity : 2
Making coffee ... DONE
COFFEE MACHINE → Ready
water quantity : 1
beans quantity : 1
Making coffee ... DONE
COFFEE MACHINE → NoIngredients
water quantity : 0
beans quantity : 0
COFFEE MACHINE → Off
water quantity : 0
beans quantity : 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment