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.
Example 1:
// Step 3: Client code
fun main(args: Array<String>) {
val context = Context()
println(context.currentState)
context.goWild()
println(context.currentState)
context.calmDown()
print(context.currentState)
}
// Step 1: Define various state via "sealed class"
sealed class State {
class RobertBruceBanner : State()
class GreenHulk : State()
}
// Step 2: Create context class
class Context {
private var state: State = State.RobertBruceBanner()
fun goWild() {
state = State.GreenHulk()
}
fun calmDown() {
state = State.RobertBruceBanner()
}
val currentState: String
get() = when(state){
is State.RobertBruceBanner -> "I am calm."
is State.GreenHulk -> "I am wild."
}
}
/**
prints
I am calm.
I am wild.
I am calm.
**/
Example 2:
My way of move depends on which ground I am on (a.k.a., my state):
- I walk on land;
- I swim in water;
- I skip on ice
So, behavior depends on state.
// Step 3: Client code
fun main(args: Array<String>) {
val myContext = MyContext()
myContext.state = MyState.StateOnLand()
println(myContext)
myContext.state.move()
myContext.state = MyState.StateOnIce()
println(myContext)
myContext.state.move()
myContext.state = MyState.StateInWater()
println(myContext)
myContext.state.move()
}
// Step 1: Define various states via sealed class
sealed class MyState{
class StateOnLand: MyState(){
override fun move() {
println("I walk on land\n")
}
}
class StateInWater: MyState(){
override fun move(){
println("I swim in water\n")
}
}
class StateOnIce: MyState(){
override fun move() {
println("I skip on ice\n")
}
}
abstract fun move()
}
// Step 2: Create a context class
class MyContext{
var state: MyState = MyState.StateOnIce()
override fun toString(): String {
return state.javaClass.simpleName + ":"
}
}
/**
prints
StateOnLand:
I walk on land
StateOnIce:
I skip on ice
StateInWater:
I swim in water
**/