Builder-Muster
Teil des Abschnitts Objektorientierte Programmierung der Ruby-Journey von Coddy. Lektion 48 von 57.
Das Builder-Muster erstellt ein komplexes Objekt Schritt für Schritt. Jeder Schritt ist eine Methode, die eine Auswahl speichert und den Builder zurückgibt, sodass die Schritte verkettet werden können; build überprüft die Auswahlen und gibt das fertige Objekt zurück:
class Pizza
def initialize(size, toppings)
@size = size
@toppings = toppings
end
def to_s
"#{@size} pizza with #{@toppings.join(", ")}"
end
end
class PizzaBuilder
def initialize
@toppings = []
end
def size(value)
@size = value
self
end
def topping(name)
@toppings << name
self
end
def build
raise ArgumentError, "size is required" if @size.nil?
Pizza.new(@size, @toppings)
end
end
puts PizzaBuilder.new.size("large").topping("cheese").topping("ham").buildAusgabe:
large pizza with cheese, hamDa der Builder das Objekt erst in build erstellt, kann er die gesamte Kombination auf einmal überprüfen, etwa auf ein erforderliches Teil oder zwei Optionen, die nicht zusammen verwendet werden können:
class TicketBuilder
def seat(value)
@seat = value
self
end
def standing
@standing = true
self
end
def build
raise ArgumentError, "seat and standing exclude each other" if @seat && @standing
@standing ? "standing ticket" : "ticket for seat #{@seat || "any"}"
end
end
puts TicketBuilder.new.seat("B7").build
puts TicketBuilder.new.standing.build
begin
TicketBuilder.new.seat("A1").standing.build
rescue ArgumentError => e
puts e.message
endAusgabe:
ticket for seat B7
standing ticket
seat and standing exclude each otherEine übliche Ruby-Form übergibt den Builder an einen Block. Die Klassenmethode erstellt den Builder, übergibt ihn und ruft am Ende build auf:
class Email
attr_accessor :to, :subject, :lines
def self.compose
email = new
email.lines = []
yield email
email
end
def to_s
"To: #{to}\nSubject: #{subject}\n\n#{lines.join("\n")}"
end
end
mail = Email.compose do |e|
e.to = "ada@x.io"
e.subject = "Hi"
e.lines << "Hello Ada,"
e.lines << "see you soon."
end
puts mailAusgabe:
To: ada@x.io
Subject: Hi
Hello Ada,
see you soon.Für eine Handvoll optionaler Werte reichen Rubys Schlüsselwortargumente mit Standardwerten oft aus. Ein Builder lohnt sich, wenn Teile wiederholt vorkommen können, die Reihenfolge wichtig ist oder die Kombination geprüft werden muss, bevor das Objekt erstellt wird:
Pizza.new(size: "large", crust: "thin") # wenige Optionen: Schlüsselwörter
Query.new.from("users").where("age > 18").where("active = 1").limit(10).to_sAufgabe
EinfachVervollständige PizzaBuilder und Pizza. Die Schritte des Builders size(value), crust(value) und topping(name) (wiederholbar) geben den Builder zurück. build löst ArgumentError mit size is required aus, wenn keine Größe angegeben wurde, verwendet classic als Teig, wenn keiner ausgewählt wurde, und gibt eine Pizza zurück. Pizza#to_s gibt large thin pizza with cheese, ham oder small classic pizza with no toppings zurück.
Jede Eingabezeile ist eine Bestellung wie size=large crust=thin topping=cheese topping=ham. Der bereitgestellte Code sendet jeden Teil der Reihe nach durch Verkettung an den Builder und gibt die Pizza oder die Fehlermeldung aus.
Dein Code gehört in pizza.rb und pizza_builder.rb. main.rb enthält den bereitgestellten Ein-/Ausgabecode und darf nicht bearbeitet werden.
Probier es selbst
require_relative 'pizza'
require_relative 'pizza_builder'
# Mitgelieferter Ein-/Ausgabecode: belasse ihn wie er ist
input = []
while (line = gets)
input << line.chomp
end
input.each do |line|
builder = line.split.reduce(PizzaBuilder.new) do |b, part|
step, value = part.split("=")
b.public_send(step, value)
end
begin
puts builder.build
rescue ArgumentError => e
puts e.message
end
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