Wzorzec obserwatora
Część sekcji Programowanie obiektowe ścieżki Ruby w Coddy. Lekcja 44 z 57.
Wzorzec obserwatora pozwala obiektom subskrybować zmiany innego obiektu, podmiotu. Podmiot przechowuje listę obserwatorów i powiadamia każdego z nich, gdy coś się wydarzy, nie wiedząc, co z tym zrobią:
class Thermometer
def initialize
@observers = []
end
def subscribe(observer)
@observers << observer
end
def temperature=(value)
@temperature = value
@observers.each { |o| o.update(value) }
end
end
class Display
def update(value)
puts "display: #{value} C"
end
end
class Alarm
def update(value)
puts "alarm: too hot!" if value > 30
end
end
t = Thermometer.new
t.subscribe(Display.new)
t.subscribe(Alarm.new)
t.temperature = 25
t.temperature = 35Wynik:
display: 25 C
display: 35 C
alarm: too hot!Obserwatorzy potrzebują tylko metody update: typowania strukturalnego. Każdy może być zupełnie inną klasą, a nowych obserwatorów można dodawać bez zmieniania obiektu obserwowanego:
class Logger2
def update(value)
@history = (@history || []) << value
end
end
thermometer.subscribe(Logger2.new) # obiekt jest bez zmianObserwatory mogą być również blokami. Obiekt przechowuje je jako procki i wywołuje za pomocą call. unsubscribe ponownie usuwa obserwator:
class Button
def initialize
@handlers = []
end
def on_click(&handler)
@handlers << handler
handler
end
def unsubscribe(handler)
@handlers.delete(handler)
end
def click
@handlers.map { |h| h.call("clicked") }
end
end
b = Button.new
b.on_click { |e| "A got #{e}" }
second = b.on_click { |e| "B got #{e}" }
p b.click
b.unsubscribe(second)
p b.clickWynik:
["A got clicked", "B got clicked"]
["A got clicked"]Podmiot decyduje, co wysłać. Przekazanie samego podmiotu pozwala obserwatorowi odczytać potrzebne mu dane; przekazanie nazwy zdarzenia pozwala jednemu obserwatorowi reagować na kilka rodzajów zmian:
@observers.each { |o| o.update(self) } # obserwator odczytuje subject.price
@observers.each { |o| o.update(:sold_out, self) } # obserwator sprawdza zdarzenieWyzwanie
ŁatwyUzupełnij obiekt Stock i dwóch obserwatorów. Stock.new(symbol) ma metody subscribe(observer) i update_price(value). Ta druga zapisuje cenę i zwraca nie-nil odpowiedzi wywołania update(stock) na każdym obserwatorze, w kolejności subskrypcji. PriceDisplay#update zwraca AAPL now 12.50. PriceAlert.new(limit) zwraca ALERT AAPL above 100.00, gdy cena wzrośnie powyżej limitu, jeśli wcześniej była na tym limicie lub poniżej niego, a w przeciwnym razie zwraca nil.
Pierwszy wiersz wejściowy zawiera symbol i limit alertu. Dostarczony kod subskrybuje wyświetlacz i alert, a następnie wypisuje odpowiedzi dla każdego wiersza set price.
Twój kod umieść w plikach stock.rb, price_display.rb i price_alert.rb. main.rb zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.
Spróbuj swoich sił
require_relative 'stock'
require_relative 'price_display'
require_relative 'price_alert'
# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
input = []
while (line = gets)
input << line.chomp
end
symbol, limit = input[0].split
stock = Stock.new(symbol)
stock.subscribe(PriceDisplay.new)
stock.subscribe(PriceAlert.new(limit.to_f))
input.drop(1).each do |line|
stock.update_price(line.split[1].to_f).each { |reply| puts reply }
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