Pattern State
Fa parte della sezione Programmazione orientata agli oggetti del percorso Ruby di Coddy. Lezione 49 di 57.
Il pattern state sposta il comportamento che dipende dallo stato corrente di un oggetto in oggetti di stato separati. L'oggetto principale, il contesto, conserva uno stato e gli inoltra le chiamate; uno stato risponde e decide quale stato viene dopo:
class Red
def next_state
Green.new
end
def to_s
"red"
end
end
class Green
def next_state
Yellow.new
end
def to_s
"green"
end
end
class Yellow
def next_state
Red.new
end
def to_s
"yellow"
end
end
class TrafficLight
def initialize
@state = Red.new
end
def change
@state = @state.next_state
self
end
def to_s
"light is #{@state}"
end
end
light = TrafficLight.new
puts light
puts light.change
puts light.change.changeOutput:
light is red
light is green
light is redSenza il pattern, ogni metodo del contesto ha bisogno di un case su un valore di stato, e un nuovo stato significa modificare tutti questi metodi. Con gli oggetti stato, ogni stato è una classe che contiene le proprie regole:
# senza il pattern
def can_go?
case @status
when :red then false
when :green then true
when :yellow then false
end
end
# con il pattern
def can_go?
@state.can_go?
endGli stati possono rifiutare un evento non appropriato. Qui una bozza non può essere pubblicata direttamente; prima deve passare dalla revisione:
class Draft
def submit
Review.new
end
def publish
raise ArgumentError, "cannot publish a draft"
end
def to_s
"draft"
end
end
class Review
def publish
Published.new
end
def to_s
"in review"
end
end
class Published
def to_s
"published"
end
end
state = Draft.new
begin
state.publish
rescue ArgumentError => e
puts e.message
end
state = state.submit
state = state.publish
puts stateOutput:
cannot publish a draft
publishedUna classe base condivisa può fornire a ogni stato la risposta predefinita, ad esempio rifiutare ogni evento, così ogni stato definisce solo gli eventi che accetta:
class State
def submit
raise ArgumentError, "cannot submit #{self}"
end
def approve
raise ArgumentError, "cannot approve #{self}"
end
end
class Review < State
def approve
Published.new
end
endSfida
FacileCompleta il semaforo. Gli stati Red, Green e Yellow hanno ciascuno next_state (il rosso passa al verde, il verde al giallo, il giallo al rosso), can_go? (solo il verde) e to_s (il colore). TrafficLight parte dal rosso, change passa allo stato successivo e status restituisce red: stop o green: go, interrogando lo stato.
Il codice fornito legge i comandi change o status e stampa lo stato dopo ogni comando.
Il tuo codice va inserito in red.rb, green.rb, yellow.rb e traffic_light.rb. main.rb contiene il codice di input/output fornito e non può essere modificato.
Provalo tu
require_relative 'red'
require_relative 'green'
require_relative 'yellow'
require_relative 'traffic_light'
# Supplied input/output code: keep it as it is
input = []
while (line = gets)
input << line.chomp
end
light = TrafficLight.new
input.each do |cmd|
light.change if cmd == "change"
puts light.status
end
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
1Classi e oggetti
Lavorare con i fileDefinire le classiVariabili d'istanzaMetodi e selfto_s e inspectRipasso - Tessera della biblioteca4Incapsulamento
Metodi privatiMetodi protettiSetter privatiProteggere lo statoRiepilogo - Distributore automatico7Polimorfismo e Duck Typing
PolimorfismoDuck TypingMetodi astratticase e classiRiepilogo - Metodi di pagamento10Pattern di progettazione Parte 2
Delegazione con ForwardablePattern DecoratorPattern BuilderPattern State2Metodi di accesso e self
Metodi di lettura e scritturaSetter personalizzatiself nei metodiIdentità e uguaglianzaRiepilogo - Elenco contatti5Ereditarietà
SottoclassiRidefinizione dei metodiChiamare superis_a? e antenatiRiepilogo - Paghe del personale8Metodi speciali
Uguaglianza e hashMetodi degli operatoriIndicizzazione e appendCollezioni personalizzateRiepilogo - Frazioni11Progetto: Gestione della biblioteca
Libri e iscrittiPrendere in prestito i libriEsercitati da solo: Compilatore Ruby online