kotlinintermediate
State Machines with Enums and Sealed Classes
Model state machines with Kotlin enums and sealed classes for type-safe state transitions.
kotlinPress ⌘/Ctrl + Shift + C to copy
enum class OrderStatus {
PENDING, CONFIRMED, SHIPPED, DELIVERED, CANCELLED;
fun canTransitionTo(next: OrderStatus): Boolean = when (this) {
PENDING -> next in setOf(CONFIRMED, CANCELLED)
CONFIRMED -> next in setOf(SHIPPED, CANCELLED)
SHIPPED -> next == DELIVERED
DELIVERED -> false
CANCELLED -> false
}
}
sealed class ConnectionState {
object Disconnected : ConnectionState()
data class Connecting(val attempt: Int) : ConnectionState()
data class Connected(val sessionId: String, val connectedAt: Long) : ConnectionState()
data class Error(val message: String, val retryAfter: Long) : ConnectionState()
fun display(): String = when (this) {
is Disconnected -> "Disconnected"
is Connecting -> "Connecting (attempt $attempt)..."
is Connected -> "Connected (session: $sessionId)"
is Error -> "Error: $message (retry in ${retryAfter}ms)"
}
}
class StateMachine<S, E>(
private var state: S,
private val transitions: Map<Pair<S, E>, (S) -> S>
) {
fun current() = state
fun transition(event: E): S {
val key = Pair(state, event)
val handler = transitions[key]
?: throw IllegalStateException("No transition from $state on $event")
state = handler(state)
return state
}
class Builder<S, E> {
private val t = mutableMapOf<Pair<S, E>, (S) -> S>()
fun on(state: S, event: E, action: (S) -> S) { t[Pair(state, event)] = action }
fun build(initial: S) = StateMachine(initial, t)
}
}
fun <S, E> stateMachine(initial: S, block: StateMachine.Builder<S, E>.() -> Unit) =
StateMachine.Builder<S, E>().apply(block).build(initial)
enum class Light { RED, YELLOW, GREEN }
enum class Timer { TICK }
fun main() {
var status = OrderStatus.PENDING
if (status.canTransitionTo(OrderStatus.CONFIRMED)) {
status = OrderStatus.CONFIRMED
println("Order: $status")
}
var conn: ConnectionState = ConnectionState.Disconnected
println(conn.display())
conn = ConnectionState.Connecting(1)
println(conn.display())
conn = ConnectionState.Connected("sess-abc", System.currentTimeMillis())
println(conn.display())
val trafficLight = stateMachine<Light, Timer>(Light.RED) {
on(Light.RED, Timer.TICK) { Light.GREEN }
on(Light.GREEN, Timer.TICK) { Light.YELLOW }
on(Light.YELLOW, Timer.TICK) { Light.RED }
}
repeat(6) {
println("Light: ${trafficLight.current()}")
trafficLight.transition(Timer.TICK)
}
}Use Cases
- Order lifecycle management
- Connection state handling
- Game state machines and workflow engines
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
kotlinintermediate
Sealed Classes and Exhaustive when
Model restricted hierarchies with sealed classes: exhaustive when, data objects, and state machines.
Best for: Type-safe API response handling
#kotlin#sealed-class
kotlinbeginner
Enum Classes — Advanced Patterns
Use Kotlin enum classes with properties, methods, interfaces, and companion utilities.
Best for: Type-safe constant sets with behavior
#kotlin#enum
kotlinbeginner
Null Safety — Elvis, Safe Call, and let
Master Kotlin null safety: safe calls, Elvis operator, let/also scoping, and smart casts.
Best for: Safe navigation through nullable chains
#kotlin#null-safety
kotlinbeginner
Data Classes — Copy, Destructure, and Equals
Use data classes for immutable models: auto-generated equals, hashCode, copy, and destructuring.
Best for: Immutable domain models and DTOs
#kotlin#data-class