Padrão State
Parte da seção Programação Orientada a Objetos do Journey de R da Coddy. Lição 48 de 57.
Um objeto no padrão state se comporta de maneira diferente dependendo do seu estado atual. Cada estado é uma lista de funções manipuladoras, e o objeto passa cada solicitação para os manipuladores do estado em que se encontra:
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
}Saída:
green : go
yellow : slow down
red : stop
green : go Os handlers recebem um evento e retornam o próximo estado e uma resposta, portanto as transições são dados, e não uma cadeia de ifs. Uma catraca é destravada quando uma moeda é inserida e travada novamente depois que alguém passa:
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")
}Saída:
push -> blocked
coin -> unlocked
coin -> already open
push -> welcome A própria máquina é uma pequena closure: ela mantém o estado atual, procura o manipulador e responde ignored para um evento que o estado não conhece:
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")Saída:
press : light on | on
kick : ignored | on
press : light off | off Um novo estado é uma nova entrada na lista. A máquina não muda, e apenas os estados que levam ao novo estado precisam de um novo manipulador:
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")
}Saída:
press : on
overheat : fuse blown
press : ignored
repair : repaired Desafio
FácilComplete a catraca em Turnstile.R. A lista states tem os estados locked e unlocked, e cada manipulador retorna list(to = ..., say = ...):
locked:coindesbloqueia comunlocked;pushpermanece bloqueado comblocked;unlocked:coinpermanece desbloqueado comthanks, already open;pushbloqueia comwelcomee contabiliza uma passagem.
Em seguida, complete make_turnstile(), que começa bloqueada e retorna handle(event) (a resposta ou ignored para um evento desconhecido), state() e passes(). Contabilize uma passagem sempre que push for tratado no estado desbloqueado. O código fornecido lê os eventos e imprime cada resposta com o novo estado e, em seguida, o número de passagens.
Seu código deve estar em Turnstile.R. main.R contém o código fornecido de entrada/saída e não pode ser editado.
Experimente você mesmo
source("Turnstile.R")
# Código de entrada/saída fornecido: mantenha-o 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 lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação Orientada a Objetos
1Fundamentos do S3
Trabalhando com ArquivosListas com uma ClasseFunções ConstrutorasMétodos de Impressão e FormataçãoValidadores e AuxiliaresRevisão - Temperaturas4Encapsulamento em R
Closures como ObjetosAmbientes como ObjetosFunções de AcessoProtegendo o EstadoRecapitulação - Parquímetro2Genéricos e Métodos S3
Genéricos e UseMethodMétodos padrãoMétodos para genéricos baseFundamentos de NextMethodRevisão - Áreas de formas5Classes S4
Definindo classes S4Slots e acessoVerificações de validadeMétodos showRevisão - Catálogo de produtos8Classes de Referência
Definindo Classes de ReferênciaMétodos e Atualizações de CamposSemântica de CópiaHerança e callSuperRecapitulação — Fila de Tarefas11Projeto: Gerenciamento de Biblioteca
Livros e MembrosEmpréstimo de LivrosPratique por conta própria: Compilador de R online