Menu
CoddyTech

Pola State

Termasuk bagian Pemrograman Berorientasi Object dalam perjalanan R di Coddy. Pelajaran 48 dari 57.

Sebuah object dalam pola state berperilaku berbeda bergantung pada state-nya saat ini. Setiap state adalah list fungsi handler, dan object meneruskan setiap permintaan ke handler dari state yang sedang ditempatinya:

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 

Handler menerima peristiwa dan mengembalikan status berikutnya serta balasan, sehingga transisinya berupa data, bukan rangkaian if. Turnstile terbuka saat koin dimasukkan dan terkunci kembali setelah seseorang melewatinya:

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 

Mesin itu sendiri adalah closure kecil: mesin ini menyimpan state saat ini, mencari handler, lalu menjawab ignored untuk event yang tidak dikenali oleh state tersebut:

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 

State baru adalah entri baru dalam list. Mesin tidak berubah, dan hanya state yang mengarah ke state baru yang memerlukan handler baru:

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 
challenge icon

Tantangan

Mudah

Lengkapi pintu putar di Turnstile.R. list states memiliki state locked dan unlocked, dan setiap fungsi penanganan mengembalikan list(to = ..., say = ...):

  • locked: coin membuka kunci dengan unlocked; push tetap terkunci dengan blocked;
  • unlocked: coin tetap tidak terkunci dengan thanks, already open; push mengunci pintu putar dengan welcome dan menghitung satu kali lewat.

Lalu lengkapi make_turnstile(), yang dimulai dalam keadaan terkunci dan mengembalikan handle(event) (balasan, atau ignored untuk event yang tidak dikenal), state(), dan passes(). Hitung satu kali lewat setiap kali push ditangani dalam keadaan tidak terkunci. Kode yang disediakan membaca event dan mencetak setiap balasan beserta state baru, lalu jumlah kali lewat.

Tulis kodemu di Turnstile.R. main.R berisi kode input/output yang disediakan dan tidak dapat diedit.

Coba sendiri

source("Turnstile.R")

# Kode input/output yang disediakan: biarkan apa adanya
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 = "")
quiz iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Object

Latihan sendiri: Compiler R online