Wzorzec dekoratora
Część sekcji Programowanie obiektowe ścieżki Ruby w Coddy. Lekcja 47 z 57.
Wzorzec dekoratora opakowuje obiekt w inny obiekt z tym samym interfejsem, który dodaje coś przed przekazaniem wywołania dalej lub po nim. Dekoratory można łączyć w dowolnej kolejności:
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)Wynik:
coffee, milk, milk: 3.00Każdy dekorator przechowuje opakowany obiekt i przekazuje do niego wywołania, więc wspólna klasa bazowa może obsługiwać tę część. Każdy konkretny dekorator nadpisuje następnie tylko to, co zmienia:
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)Wynik:
coffee, sugar: 2.20Biblioteka standardowa SimpleDelegator (require 'delegate') przekazuje każdą metodę, której sama nie definiuje, opakowanemu obiektowi, dzięki czemu dekoratory pozostają krótkie, gdy interfejs jest rozbudowany:
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")Wynik:
HELLO!
5
trueDekoratory dodają zachowanie pojedynczym obiektom w czasie działania programu i można je dowolnie łączyć. W przypadku podklas każda kombinacja, taka jak MilkSugarCoffee, wymagałaby własnej klasy:
Sugar.new(Milk.new(Coffee.new)) # dowolna kombinacja, dowolna kolejność
Whip.new(Sugar.new(Coffee.new))
# z podklasami: MilkCoffee, SugarCoffee, MilkSugarCoffee, ...Wyzwanie
ŁatwyUzupełnij dekoratory kawy. Coffee kosztuje 2.00, a jego opis to coffee. Milk dodaje 0.50 i , milk, Sugar dodaje 0.20 i , sugar, a Whip dodaje 0.70 i , whip. Wszystkie trzy dekoratory współdzielą klasę bazową Extra, która przechowuje opakowany napój i przekazuje wywołania cost oraz description; każda podklasa używa super.
Każdy wiersz wejściowy to zamówienie, na przykład milk sugar. Dostarczony kod opakowuje nowy obiekt Coffee dekoratorami w tej kolejności i wypisuje coffee, milk, sugar: 2.70.
Twój kod umieść w plikach coffee.rb, extra.rb, milk.rb, sugar.rb i whip.rb. main.rb zawiera dostarczony kod wejścia/wyjścia i nie można go edytować.
Spróbuj swoich sił
require_relative 'coffee'
require_relative 'extra'
require_relative 'milk'
require_relative 'sugar'
require_relative 'whip'
# Dostarczony kod wejścia/wyjścia: pozostaw go bez zmian
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
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