Wzorzec stanu
Część sekcji Programowanie obiektowe ścieżki Ruby w Coddy. Lekcja 49 z 57.
Wzorzec stanu przenosi zachowanie zależne od bieżącego stanu obiektu do osobnych obiektów stanu. Główny obiekt, kontekst, przechowuje jeden stan i przekazuje do niego wywołania; stan odpowiada i decyduje, który stan będzie następny:
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.changeWynik:
light is red
light is green
light is redBez tego wzorca każda metoda kontekstu wymaga instrukcji case sprawdzającej wartość statusu, a dodanie nowego stanu oznacza konieczność edycji ich wszystkich. W przypadku obiektów stanów każdy stan jest klasą zawierającą własne reguły:
# bez wzorca
def can_go?
case @status
when :red then false
when :green then true
when :yellow then false
end
end
# z wzorcem
def can_go?
@state.can_go?
endStany mogą odrzucić zdarzenie, które do nich nie pasuje. Tutaj szkicu nie można opublikować bezpośrednio; najpierw musi przejść weryfikację:
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 stateWynik:
cannot publish a draft
publishedWspólna klasa bazowa może zapewnić każdemu stanowi domyślną odpowiedź, na przykład odrzucanie każdego zdarzenia, dzięki czemu każdy stan definiuje tylko te zdarzenia, które akceptuje:
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
endWyzwanie
ŁatwyUzupełnij sygnalizację świetlną. Stany Red, Green i Yellow mają każdy next_state (czerwony przechodzi w zielony, zielony w żółty, a żółty w czerwony), can_go? (tylko zielony) i to_s (kolor). TrafficLight zaczyna od czerwonego, change przechodzi do następnego stanu, a status zwraca red: stop lub green: go, pytając o stan.
Dostarczony kod odczytuje polecenia change lub status i wyświetla status po każdym poleceniu.
Umieść swój kod w plikach red.rb, green.rb, yellow.rb i traffic_light.rb. main.rb zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.
Spróbuj swoich sił
require_relative 'red'
require_relative 'green'
require_relative 'yellow'
require_relative 'traffic_light'
# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
input = []
while (line = gets)
input << line.chomp
end
light = TrafficLight.new
input.each do |cmd|
light.change if cmd == "change"
puts light.status
end
Ta lekcja zawiera krótki quiz. Zacznij lekcję, żeby na niego odpowiedzieć i śledzić swoje postępy.
Wszystkie lekcje w sekcji Programowanie obiektowe
1Klasy i obiekty
Praca z plikamiDefiniowanie klasZmienne instancjiMetody i selfto_s i inspectPowtórzenie – karta biblioteczna4Hermetyzacja
Metody prywatneMetody chronionePrywatne setteryOchrona stanuPowtórzenie – automat vendingowy7Polimorfizm i typowanie kacze
PolimorfizmTypowanie kaczeMetody abstrakcyjnecase i klasyPowtórzenie – metody płatności10Wzorce projektowe, część 2
Delegowanie z ForwardableWzorzec dekoratoraWzorzec budowniczegoWzorzec stanu2Metody dostępowe i self
Gettery i setteryWłasne setteryself w metodachTożsamość i równośćPowtórzenie – lista kontaktów5Dziedziczenie
PodklasyNadpisywanie metodWywoływanie superis_a? i przodkowiePowtórka – lista płac pracowników8Metody specjalne
Równość i hashMetody operatorówIndeksowanie i dodawanieWłasne kolekcjePowtórka – ułamki11Projekt: Zarządzanie biblioteką
Książki i czytelnicyWypożyczanie książekPoćwicz samodzielnie: Kompilator Ruby online