Menu
Coddy logo textTech

Dekoratör Deseni

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

Dekoratör deseni, bir nesneyi aynı arayüze sahip başka bir nesnenin içine sarar ve çağrıyı iletmeden önce veya sonra bir şey ekler. Dekoratörler herhangi bir sırayla üst üste eklenebilir:

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)

Çıktı:

coffee, milk, milk: 3.00

Her dekoratör, sarmalanan nesneyi saklar ve çağrıları ona iletir; bu nedenle ortak bir temel sınıf bu kısmı üstlenebilir. Ardından her somut dekoratör yalnızca değiştirdiği kısımları geçersiz kılar:

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)

Çıktı:

coffee, sugar: 2.20

Standart kütüphanenin SimpleDelegator sınıfı (require 'delegate'), tanımlamadığı her yöntemi sarmalanmış nesneye yönlendirir; bu da arayüz büyük olduğunda dekoratörleri kısa tutar:

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

Çıktı:

HELLO!
5
true

Decorator'lar çalışma zamanında tekil nesnelere davranış ekler ve serbestçe birleştirilebilir. Alt sınıflarla, MilkSugarCoffee gibi her bileşimin kendine ait bir sınıfa ihtiyacı olurdu:

Sugar.new(Milk.new(Coffee.new))      # herhangi bir kombinasyon, herhangi bir sıra
Whip.new(Sugar.new(Coffee.new))

# alt sınıflarla: MilkCoffee, SugarCoffee, MilkSugarCoffee, ...
challenge icon

Görev

Kolay

Kahve dekoratörlerini tamamla. Coffee 2.00 tutarındadır ve coffee olarak açıklanır. Milk 0.50 ve , milk, Sugar 0.20 ve , sugar, Whip ise 0.70 ve , whip ekler. Üç dekoratör, sarılmış içeceği depolayan ve cost ile description'ı ileten temel sınıf Extra'yı paylaşır; her alt sınıf super kullanır.

Her girdi satırı milk sugar gibi bir sipariştir. Sağlanan kod, yeni bir Coffee'yi dekoratörlerle bu sırayla sarar ve coffee, milk, sugar: 2.70 çıktısını yazdırır.

Kodun coffee.rb, extra.rb, milk.rb, sugar.rb ve whip.rb dosyalarına yazılmalıdır. main.rb sağlanan girdi/çıktı kodunu içerir ve düzenlenemez.

Kendin dene

require_relative 'coffee'
require_relative 'extra'
require_relative 'milk'
require_relative 'sugar'
require_relative 'whip'

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