Decorator-Muster
Teil des Abschnitts Objektorientierte Programmierung der Ruby-Journey von Coddy. Lektion 47 von 57.
Das Dekorator-Muster umhüllt ein Objekt mit einem anderen Objekt mit derselben Schnittstelle und fügt etwas hinzu, bevor der Aufruf weitergegeben wird oder nachdem dies geschehen ist. Dekoratoren können in beliebiger Reihenfolge gestapelt werden:
class Coffee
def cost
2.0
end
def description
"coffee"
end
end
class Milk
def initialize(drink)
@drink = drink
end
def cost
@drink.cost + 0.5
end
def description
"#{@drink.description}, milk"
end
end
order = Milk.new(Milk.new(Coffee.new))
puts format("%s: %.2f", order.description, order.cost)Ausgabe:
coffee, milk, milk: 3.00Jeder Decorator speichert das umschlossene Objekt und leitet Aufrufe an es weiter, daher kann eine gemeinsame Basisklasse diesen Teil übernehmen. Jeder konkrete Decorator überschreibt dann nur das, was er ändert:
class Coffee
def cost
2.0
end
def description
"coffee"
end
end
class Extra
def initialize(drink)
@drink = drink
end
def cost
@drink.cost
end
def description
@drink.description
end
end
class Sugar < Extra
def cost
super + 0.2
end
def description
super + ", sugar"
end
end
order = Sugar.new(Coffee.new)
puts format("%s: %.2f", order.description, order.cost)Ausgabe:
coffee, sugar: 2.20Die Standardbibliothek SimpleDelegator (require 'delegate') leitet jede Methode, die sie nicht selbst definiert, an das umschlossene Objekt weiter. Dadurch bleiben Decorators kurz, wenn die Schnittstelle umfangreich ist:
require 'delegate'
class Loud < SimpleDelegator
def to_s
super.upcase + "!"
end
end
text = Loud.new("hello")
puts text
puts text.size
puts text.start_with?("he")Ausgabe:
HELLO!
5
trueDekoratoren fügen einzelnen Objekten zur Laufzeit Verhalten hinzu und lassen sich beliebig kombinieren. Bei Unterklassen müsste es für jede Kombination eine eigene Klasse geben, zum Beispiel MilkSugarCoffee:
Sugar.new(Milk.new(Coffee.new)) # jede Kombination, jede Reihenfolge
Whip.new(Sugar.new(Coffee.new))
# mit Unterklassen: MilkCoffee, SugarCoffee, MilkSugarCoffee, ...Aufgabe
EinfachVervollständige die Kaffee-Decoratoren. Coffee kostet 2.00 und wird als coffee beschrieben. Milk fügt 0.50 und , milk hinzu, Sugar fügt 0.20 und , sugar hinzu und Whip fügt 0.70 und , whip hinzu. Die drei Decoratoren verwenden die Basisklasse Extra, die das verpackte Getränk speichert und cost und description weiterleitet; jede Unterklasse verwendet super.
Jede Eingabezeile ist eine Bestellung wie milk sugar. Der bereitgestellte Code verpackt ein neues Coffee in dieser Reihenfolge in die Decoratoren und gibt coffee, milk, sugar: 2.70 aus.
Dein Code gehört in coffee.rb, extra.rb, milk.rb, sugar.rb und whip.rb. main.rb enthält den bereitgestellten Ein-/Ausgabecode und kann nicht bearbeitet werden.
Probier es selbst
require_relative 'coffee'
require_relative 'extra'
require_relative 'milk'
require_relative 'sugar'
require_relative 'whip'
# Vorgegebener Eingabe-/Ausgabecode: unverändert lassen
input = []
while (line = gets)
input << line.chomp
end
extras = { "milk" => Milk, "sugar" => Sugar, "whip" => Whip }
input.each do |line|
drink = line.split.reduce(Coffee.new) { |d, name| extras[name].new(d) }
puts format("%s: %.2f", drink.description, drink.cost)
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