Pattern State
Fa parte della sezione Programmazione orientata agli oggetti del percorso R di Coddy. Lezione 48 di 57.
Un oggetto nel pattern state si comporta in modo diverso a seconda del suo stato attuale. Ogni stato è un elenco di funzioni handler e l'oggetto passa ogni richiesta agli handler dello stato in cui si trova:
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
}Output:
green : go
yellow : slow down
red : stop
green : go I gestori ricevono un evento e restituiscono lo stato successivo e una risposta, quindi le transizioni sono dati anziché una catena di if. Un tornello si sblocca quando viene inserita una moneta e si blocca di nuovo dopo che qualcuno è passato:
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")
}Output:
push -> blocked
coin -> unlocked
coin -> already open
push -> welcome La macchina stessa è una piccola chiusura: mantiene lo stato corrente, cerca il gestore e risponde ignored per un evento che lo stato non conosce:
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")Output:
press : light on | on
kick : ignored | on
press : light off | off Un nuovo stato è una nuova voce nell'elenco. La macchina non cambia e solo gli stati che conducono a quello nuovo necessitano di un nuovo gestore:
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")
}Output:
press : on
overheat : fuse blown
press : ignored
repair : repaired Sfida
FacileCompleta il tornello in Turnstile.R. La lista states contiene gli stati locked e unlocked e ogni gestore restituisce list(to = ..., say = ...):
- locked:
coinsblocca conunlocked;pushresta bloccato conblocked; - unlocked:
coinresta sbloccato conthanks, already open;pushblocca conwelcomee conta un passaggio.
Completa poi make_turnstile(), che inizia nello stato locked e restituisce handle(event) (la risposta, oppure ignored per un evento sconosciuto), state() e passes(). Conta un passaggio ogni volta che push viene gestito nello stato unlocked. Il codice fornito legge gli eventi e stampa ogni risposta con il nuovo stato, poi il numero di passaggi.
Il tuo codice va in Turnstile.R. main.R contiene il codice di input/output fornito e non può essere modificato.
Provalo tu
source("Turnstile.R")
# Codice di input/output fornito: lascialo così com'è
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 = "")
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Nozioni di base su S3
Lavorare con i fileListe con una classeFunzioni costruttriciMetodi di stampa e formattazioneValidatori e funzioni di supportoRipasso - Temperature4Incapsulamento in R
Chiusure come oggettiAmbienti come oggettiFunzioni di accessoProteggere lo statoRiepilogo - Parcometro2Generics e metodi S3
Generics e UseMethodMetodi predefinitiMetodi per i generics di baseNozioni di base su NextMethodRiepilogo - Aree delle forme5Classi S4
Definire le classi S4Slot e accessoControlli di validitàMetodi showRiepilogo - Catalogo prodotti8Classi di riferimento
Definizione delle classi di riferimentoMetodi e aggiornamenti dei campiSemantica della copiaEreditarietà e callSuperRiepilogo - coda di attività11Progetto: Gestione della biblioteca
Libri e iscrittiPrestito dei libriEsercitati da solo: Compilatore R online