Pattern Builder
Fa parte della sezione Programmazione orientata agli oggetti del percorso Ruby di Coddy. Lezione 48 di 57.
Il pattern builder crea un oggetto complesso passo dopo passo. Ogni passaggio è un metodo che memorizza una scelta e restituisce il builder, così i passaggi possono concatenarsi; build controlla le scelte e restituisce l’oggetto completo:
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").buildOutput:
large pizza with cheese, hamPoiché il builder crea l'oggetto solo in build, può controllare l'intera combinazione in una volta sola, ad esempio una parte obbligatoria o due opzioni che non possono coesistere:
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
endOutput:
ticket for seat B7
standing ticket
seat and standing exclude each otherUna forma comune in Ruby passa il builder a un blocco. Il metodo di classe crea il builder, vi passa il controllo e chiama build alla fine:
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 mailOutput:
To: ada@x.io
Subject: Hi
Hello Ada,
see you soon.Per un numero ridotto di valori facoltativi, gli argomenti con nome di Ruby con valori predefiniti sono spesso sufficienti. Un builder è utile quando alcune parti possono ripetersi, l’ordine è importante o è necessario verificare la combinazione prima che l’oggetto esista:
Pizza.new(size: "large", crust: "thin") # few options: keywords
Query.new.from("users").where("age > 18").where("active = 1").limit(10).to_sSfida
FacileCompleta PizzaBuilder e Pizza. I passaggi del builder size(value), crust(value) e topping(name) (ripetibile) restituiscono il builder. build solleva ArgumentError con size is required quando non è stata specificata una dimensione, usa la crosta classic quando non ne è stata scelta una e restituisce una Pizza. Pizza#to_s restituisce large thin pizza with cheese, ham oppure small classic pizza with no toppings.
Ogni riga di input è un ordine, ad esempio size=large crust=thin topping=cheese topping=ham. Il codice fornito invia ogni parte al builder nell'ordine, concatenando le chiamate, e stampa la pizza o il messaggio di errore.
Il tuo codice va inserito in pizza.rb e pizza_builder.rb. main.rb contiene il codice di input/output fornito e non può essere modificato.
Provalo tu
require_relative 'pizza'
require_relative 'pizza_builder'
# Código de entrada/salida proporcionado: déjalo tal como está
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
Questa lezione include un breve quiz. Inizia la lezione per rispondere e tenere traccia dei tuoi progressi.
Tutte le lezioni di Programmazione orientata agli oggetti
1Classi e oggetti
Lavorare con i fileDefinire le classiVariabili d'istanzaMetodi e selfto_s e inspectRipasso - Tessera della biblioteca4Incapsulamento
Metodi privatiMetodi protettiSetter privatiProteggere lo statoRiepilogo - Distributore automatico7Polimorfismo e Duck Typing
PolimorfismoDuck TypingMetodi astratticase e classiRiepilogo - Metodi di pagamento10Pattern di progettazione Parte 2
Delegazione con ForwardablePattern DecoratorPattern BuilderPattern State2Metodi di accesso e self
Metodi di lettura e scritturaSetter personalizzatiself nei metodiIdentità e uguaglianzaRiepilogo - Elenco contatti5Ereditarietà
SottoclassiRidefinizione dei metodiChiamare superis_a? e antenatiRiepilogo - Paghe del personale8Metodi speciali
Uguaglianza e hashMetodi degli operatoriIndicizzazione e appendCollezioni personalizzateRiepilogo - Frazioni11Progetto: Gestione della biblioteca
Libri e iscrittiPrendere in prestito i libriEsercitati da solo: Compilatore Ruby online