Patrón State
Parte de la sección Programación orientada a objetos del Journey de R de Coddy. Lección 48 de 57.
Un objeto en el patrón de estado se comporta de manera diferente según su estado actual. Cada estado es una lista de funciones controladoras, y el objeto pasa cada solicitud a las controladoras del estado en el que se encuentra:
states <- list(
green = list(label = "go", next_state = "yellow"),
yellow = list(label = "slow down", next_state = "red"),
red = list(label = "stop", next_state = "green")
)
current <- "green"
for (i in 1:4) {
cat(current, ":", states[[current]]$label, "\n")
current <- states[[current]]$next_state
}Salida:
green : go
yellow : slow down
red : stop
green : go Los controladores reciben un evento y devuelven el estado siguiente y una respuesta, por lo que las transiciones son datos en lugar de una cadena de if. Un torniquete se desbloquea cuando se inserta una moneda y vuelve a bloquearse después de que alguien pasa:
states <- list(
locked = list(
coin = function() list(to = "unlocked", say = "unlocked"),
push = function() list(to = "locked", say = "blocked")
),
unlocked = list(
coin = function() list(to = "unlocked", say = "already open"),
push = function() list(to = "locked", say = "welcome")
)
)
current <- "locked"
for (event in c("push", "coin", "coin", "push")) {
r <- states[[current]][[event]]()
current <- r$to
cat(event, "->", r$say, "\n")
}Salida:
push -> blocked
coin -> unlocked
coin -> already open
push -> welcome La máquina en sí es un cierre pequeño: mantiene el estado actual, busca el controlador y responde ignored para un evento que el estado no reconoce:
make_machine <- function(states, start) {
current <- start
list(
handle = function(event) {
h <- states[[current]][[event]]
if (is.null(h)) return("ignored")
r <- h()
current <<- r$to
r$say
},
state = function() current
)
}
states <- list(off = list(press = function() list(to = "on", say = "light on")),
on = list(press = function() list(to = "off", say = "light off")))
m <- make_machine(states, "off")
for (e in c("press", "kick", "press")) cat(e, ":", m$handle(e), "|", m$state(), "\n")Salida:
press : light on | on
kick : ignored | on
press : light off | off Un nuevo estado es una nueva entrada en la lista. La máquina no cambia, y solo los estados que conducen al nuevo necesitan un nuevo controlador:
states <- list(
off = list(press = function() list(to = "on", say = "on")),
on = list(press = function() list(to = "off", say = "off"),
overheat = function() list(to = "broken", say = "fuse blown")),
broken = list(repair = function() list(to = "off", say = "repaired"))
)
current <- "off"
for (e in c("press", "overheat", "press", "repair")) {
h <- states[[current]][[e]]
if (is.null(h)) { cat(e, ": ignored\n"); next }
r <- h()
current <- r$to
cat(e, ":", r$say, "\n")
}Salida:
press : on
overheat : fuse blown
press : ignored
repair : repaired Desafío
FácilCompleta el torniquete en Turnstile.R. La lista states tiene los estados locked y unlocked, y cada controlador devuelve list(to = ..., say = ...):
- locked:
coindesbloquea conunlocked;pushpermanece bloqueado conblocked; - unlocked:
coinpermanece desbloqueado conthanks, already open;pushbloquea conwelcomey cuenta un paso.
Después completa make_turnstile(), que comienza bloqueado y devuelve handle(event) (la respuesta, o ignored para un evento desconocido), state() y passes(). Cuenta un paso cada vez que se gestiona push en el estado desbloqueado. El código proporcionado lee los eventos e imprime cada respuesta con el nuevo estado y, después, los pasos.
Tu código va en Turnstile.R. main.R contiene el código de entrada/salida proporcionado y no se puede editar.
Pruébalo tú mismo
source("Turnstile.R")
# Código de entrada/salida suministrado: déjalo tal como está
input <- suppressWarnings(readLines(file("stdin")))
t <- make_turnstile()
for (event in input) cat(event, ": ", t$handle(event), " [", t$state(), "]\n", sep = "")
cat("passes: ", t$passes(), "\n", sep = "")
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación orientada a objetos
1Fundamentos de S3
Trabajar con archivosListas con una claseFunciones constructorasMétodos de impresión y formatoValidadores y auxiliaresRepaso: temperaturas4Encapsulación en R
Cierres como objetosEntornos como objetosFunciones de accesoProtección del estadoRepaso: parquímetro2S3 Genéricos y métodos
Genéricos y UseMethodMétodos predeterminadosMétodos para genéricos baseFundamentos de NextMethodRepaso: áreas de figuras5Clases S4
Definición de clases S4Slots y accesoComprobaciones de validezMétodos showRepaso - Catálogo de productos8Clases de referencia
Definición de clases de referenciaMétodos y actualizaciones de camposSemántica de copiaHerencia y callSuperRepaso: cola de tareas11Proyecto: Gestión de biblioteca
Libros y miembrosPréstamo de librosPractica por tu cuenta: Compilador de R online