Decorator-Muster
Teil des Abschnitts Objektorientierte Programmierung der Ruby-Journey von Coddy. Lektion 47 von 57.
Das Decorator-Muster verpackt ein Objekt in ein anderes Objekt mit derselben Schnittstelle, das etwas hinzufügt, bevor der Aufruf weitergeleitet wird, oder danach. Decorators 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 stellt mit SimpleDelegator (require 'delegate') einen Delegator bereit, der jede Methode, die er nicht selbst definiert, an das umschlossene Objekt weiterleitet. Dadurch bleiben Dekoratoren 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 können frei kombiniert werden. Bei Unterklassen bräuchte jede Kombination wie MilkSugarCoffee eine eigene Klasse:
Sugar.new(Milk.new(Coffee.new)) # beliebige Kombination, beliebige Reihenfolge
Whip.new(Sugar.new(Coffee.new))
# mit Unterklassen: MilkCoffee, SugarCoffee, MilkSugarCoffee, ...Aufgabe
EinfachVervollständige die Kaffee-Dekoratoren. 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 Dekoratoren teilen sich die Basisklasse Extra, die das umschlossene Getränk speichert und cost sowie description weiterleitet; jede Unterklasse verwendet super.
Jede Eingabezeile ist eine Bestellung wie milk sugar. Der bereitgestellte Code umschließt ein neues Coffee in dieser Reihenfolge mit den Dekoratoren 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 Eingabe-/Ausgabecode und kann nicht bearbeitet werden.
Probier es selbst
require_relative 'coffee'
require_relative 'extra'
require_relative 'milk'
require_relative 'sugar'
require_relative 'whip'
# Gelieferter Input/Output-Code: belasse ihn wie er ist
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