State-Muster
Teil des Abschnitts Objektorientierte Programmierung der Ruby-Journey von Coddy. Lektion 49 von 57.
Das State-Muster verschiebt Verhalten, das vom aktuellen Zustand eines Objekts abhängt, in separate Zustandsobjekte. Das Hauptobjekt, der Kontext, enthält einen Zustand und leitet Aufrufe an ihn weiter; ein Zustand antwortet und entscheidet, welcher Zustand als Nächstes folgt:
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.changeAusgabe:
light is red
light is green
light is redOhne das Muster benötigt jede Methode des Kontexts ein case für einen Statuswert, und ein neuer Zustand bedeutet, dass alle Methoden bearbeitet werden müssen. Bei Zustandsobjekten ist jeder Zustand eine Klasse, die ihre eigenen Regeln enthält:
# ohne das Muster
def can_go?
case @status
when :red then false
when :green then true
when :yellow then false
end
end
# mit dem Muster
def can_go?
@state.can_go?
endZustände können ein Ereignis ablehnen, das nicht passt. Hier kann ein Entwurf nicht direkt veröffentlicht werden; er muss zuerst überprüft werden:
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 stateAusgabe:
cannot publish a draft
publishedEine gemeinsame Basisklasse kann jedem Zustand die Standardantwort geben, beispielsweise jedes Ereignis abzulehnen, sodass jeder Zustand nur die Ereignisse definiert, die er akzeptiert:
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
endAufgabe
EinfachVervollständige die Ampel. Die Zustände Red, Green und Yellow verfügen jeweils über next_state (rot geht zu grün, grün zu gelb, gelb zu rot), can_go? (nur grün) und to_s (die Farbe). TrafficLight startet mit Rot, change wechselt zum nächsten Zustand, und status gibt red: stop oder green: go zurück, indem der Zustand abgefragt wird.
Der bereitgestellte Code liest die Befehle change oder status ein und gibt nach jedem Befehl den Status aus.
Dein Code gehört in red.rb, green.rb, yellow.rb und traffic_light.rb. main.rb enthält den bereitgestellten Eingabe-/Ausgabecode und kann nicht bearbeitet werden.
Probier es selbst
require_relative 'red'
require_relative 'green'
require_relative 'yellow'
require_relative 'traffic_light'
# Bereitgestellter Ein-/Ausgabe-Code: belasse ihn wie er ist
input = []
while (line = gets)
input << line.chomp
end
light = TrafficLight.new
input.each do |cmd|
light.change if cmd == "change"
puts light.status
end
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Klassen und Objekte
Arbeiten mit DateienKlassen definierenInstanzvariablenMethoden und selfto_s und inspectRückblick – Bibliotheksausweis4Kapselung
Private MethodenGeschützte MethodenPrivate SetterZustand schützenRückblick – Verkaufsautomat7Polymorphismus und Duck Typing
PolymorphismusDuck TypingAbstrakte MethodenFälle und KlassenRückblick – Zahlungsmethoden2Getter und Setter sowie self
Leser und SchreiberBenutzerdefinierte Setterself in MethodenIdentität und GleichheitWiederholung – Kontaktliste5Vererbung
UnterklassenMethoden überschreibensuper aufrufenis_a? und VorfahrenRückblick – Gehaltsabrechnung des Personals8Spezielle Methoden
Gleichheit und HashOperator-MethodenIndexieren und AnhängenBenutzerdefinierte CollectionsRückblick – Brüche11Projekt: Bibliotheksverwaltung
Bücher und MitgliederBücher ausleihenÜbe selbstständig: Online-Ruby-Compiler