Beobachtermuster
Teil des Abschnitts Objektorientierte Programmierung der Ruby-Journey von Coddy. Lektion 44 von 57.
Das Observer-Muster ermöglicht es Objekten, Änderungen eines anderen Objekts, des Subjekts, zu abonnieren. Das Subjekt verwaltet eine Liste von Beobachtern und benachrichtigt jeden einzelnen, wenn etwas geschieht, ohne zu wissen, was sie damit machen:
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 = 35Ausgabe:
display: 25 C
display: 35 C
alarm: too hot!Die Beobachter benötigen lediglich eine update-Methode: Duck-Typing. Jeder kann eine völlig andere Klasse sein, und neue Beobachter können hinzugefügt werden, ohne das Subjekt zu ändern:
class Logger2
def update(value)
@history = (@history || []) << value
end
end
thermometer.subscribe(Logger2.new) # das Subjekt ist unverändertBeobachter können ebenfalls Blöcke sein. Das Subjekt speichert sie als Procs und ruft sie mit call auf. unsubscribe entfernt einen Beobachter wieder:
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.clickAusgabe:
["A got clicked", "B got clicked"]
["A got clicked"]Das Subjekt entscheidet, was gesendet werden soll. Wenn du das Subjekt selbst übergibst, kann ein Observer die benötigten Informationen lesen; wenn du einen Ereignisnamen übergibst, kann ein Observer auf mehrere Arten von Änderungen reagieren:
@observers.each { |o| o.update(self) } # Beobachter liest subject.price
@observers.each { |o| o.update(:sold_out, self) } # Beobachter prüft das EventAufgabe
EinfachVervollständige die Klasse Stock und zwei Beobachter. Stock.new(symbol) verfügt über subscribe(observer) und update_price(value), wobei der Preis gespeichert wird und die nicht-nil-Antworten von update(stock) für jeden Beobachter in der Reihenfolge der Anmeldung zurückgegeben werden. PriceDisplay#update gibt AAPL now 12.50 zurück. PriceAlert.new(limit) gibt ALERT AAPL above 100.00 zurück, wenn der Preis von einem Wert am oder unter dem Limit über das Limit steigt, und andernfalls nil.
Die erste Eingabezeile enthält das Symbol und das Alarmlimit. Der bereitgestellte Code abonniert eine Anzeige und einen Alarm und gibt anschließend die Antworten für jede set price-Zeile aus.
Dein Code gehört in stock.rb, price_display.rb und price_alert.rb. main.rb enthält den bereitgestellten Ein-/Ausgabecode und kann nicht bearbeitet werden.
Probier es selbst
require_relative 'stock'
require_relative 'price_display'
require_relative 'price_alert'
# Bereitgestellter Ein-/Ausgabe-Code: belasse ihn unverändert
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
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