Menu
Coddy logo textTech

Oluşturucu Deseni

Coddy'nin Ruby Journey'sinin Nesne Yönelimli Programlama bölümünün bir parçası. Ders 48 / 57.

builder deseni karmaşık bir nesneyi adım adım oluşturur. Her adım, bir seçimi depolayan ve oluşturucuyu döndüren bir yöntemdir; böylece adımlar zincirlenir. build seçimleri denetler ve tamamlanmış nesneyi döndürür:

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").build

Çıktı:

large pizza with cheese, ham

Oluşturucu nesneyi yalnızca build içinde oluşturduğundan, zorunlu bir parça veya birlikte kullanılamayan iki seçenek gibi tüm birleşimi aynı anda kontrol edebilir:

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
end

Çıktı:

ticket for seat B7
standing ticket
seat and standing exclude each other

Yaygın bir Ruby biçimi, oluşturucuyu bir bloğa verir. Sınıf metodu oluşturucuyu oluşturur, ona yield eder ve sonunda build çağrısını yapar:

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 mail

Çıktı:

To: ada@x.io
Subject: Hi

Hello Ada,
see you soon.

Bir avuç isteğe bağlı değer için Ruby'nin varsayılan değerlere sahip anahtar sözcük bağımsız değişkenleri çoğu zaman yeterlidir. Parçalar tekrarlanabildiğinde, sıra önemli olduğunda veya birleşimin nesne oluşturulmadan önce doğrulanması gerektiğinde builder kullanmak avantaj sağlar:

Pizza.new(size: "large", crust: "thin")          # az seçenek: keywords

Query.new.from("users").where("age > 18").where("active = 1").limit(10).to_s
challenge icon

Görev

Kolay

PizzaBuilder ve Pizza sınıflarını tamamla. Builder'ın size(value), crust(value) ve topping(name) (tekrarlanabilir) adımları builder'ı döndürür. build, boyut verilmediğinde ArgumentError hatasını size is required ile birlikte yükseltir, hiçbiri seçilmediğinde kabuk olarak classic kullanır ve bir Pizza döndürür. Pizza#to_s, large thin pizza with cheese, ham veya small classic pizza with no toppings döndürür.

Her girdi satırı size=large crust=thin topping=cheese topping=ham gibi bir sipariştir. Sağlanan kod, zincirleme yöntem çağrılarıyla her parçayı sırayla builder'a gönderir ve pizzayı veya hata mesajını yazdırır.

Kodun pizza.rb ve pizza_builder.rb dosyalarına yazılmalıdır. main.rb sağlanan girdi/çıktı kodunu içerir ve düzenlenemez.

Kendin dene

require_relative 'pizza'
require_relative 'pizza_builder'

# Sağlanan girdi/çıktı kodu: olduğu gibi bırakın
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
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Nesne Yönelimli Programlama bölümündeki tüm dersler

Kendi başına pratik yap: Online Ruby derleyicisi