Menu
Coddy logo textTech

Strateji Deseni

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

strateji deseni, bir algoritmanın bir bölümünü kendi nesnesine yerleştirir ve ana nesnenin bu bölümü devretmesini sağlar. Stratejiyi değiştirmek, ana sınıfı değiştirmeden davranışı değiştirir:

class Standard
  def cost(kg)
    5 + kg * 1.5
  end
end

class Express
  def cost(kg)
    15 + kg * 3
  end
end

class Shipment
  attr_writer :strategy

  def initialize(kg, strategy)
    @kg = kg
    @strategy = strategy
  end

  def cost
    @strategy.cost(@kg)
  end
end

s = Shipment.new(2, Standard.new)
puts s.cost
s.strategy = Express.new
puts s.cost

Çıktı:

8.0
21

Stratejiler yalnızca bir yöntem adını paylaşır; bu nedenle cost özelliğine sahip herhangi bir nesne çalışır: yine ördek tiplemesi. Yeni bir gönderim yöntemi eklemek, Shipment içinde başka bir dal eklemek yerine tek bir sınıf eklemek anlamına gelir:

class Pickup
  def cost(_kg)
    0
  end
end

shipment.strategy = Pickup.new     # Shipment değişmedi

Ruby'de bir strateji genellikle bir lambda'dır. call'a yanıt veren her şey, lambda, bir yöntem nesnesi veya kendi sınıfınızdan bir nesne olması fark etmeksizin saklanabilir ve çağrılabilir:

class TextFormatter
  def initialize(strategy)
    @strategy = strategy
  end

  def format_all(words)
    words.map { |w| @strategy.call(w) }.join(" ")
  end
end

class Censor
  def call(word)
    word.size > 3 ? "*" * word.size : word
  end
end

words = %w[ruby is great]
puts TextFormatter.new(->(w) { w.upcase }).format_all(words)
puts TextFormatter.new(:capitalize.to_proc).format_all(words)
puts TextFormatter.new(Censor.new).format_all(words)

Çıktı:

RUBY IS GREAT
Ruby Is Great
**** is *****

Program çalışırken bir nesnenin davranışını değiştirmesi gerektiğinde veya değişiklik tek bir adımdan oluştuğunda, alt sınıflar yerine stratejiyi tercih edin. Bir alt sınıf, davranışı nesnenin tüm yaşamı boyunca sabitler:

# alt sınıflama: oluşturma anında sabit
ExpressShipment.new(2)

# strateji: daha sonra değiştirilebilir
shipment = Shipment.new(2, Standard.new)
shipment.strategy = Express.new
challenge icon

Görev

Kolay

Gönderim stratejilerini ve ShippingCalculator sınıfını tamamla. Standard#cost(kg), 5 artı kg başına 1.50; Express#cost(kg), 15 artı kg başına 3 ve Pickup#cost(kg), 0 değerindedir. Hesaplayıcı bir stratejiyle oluşturulur, strategy= ile strateji değiştirilebilir ve quote(kg), stratejinin sınıf adını kullanarak 2.5 kg by Express: 22.50 değerini döndürür.

Sağlanan kod Standard ile başlar ve use express, use pickup, use standard veya quote 2.5 komutlarını okur; her fiyat teklifini yazdırır.

Kodun standard.rb, express.rb, pickup.rb ve shipping_calculator.rb dosyalarına yazılmalıdır. main.rb, sağlanan girdi/çıktı kodunu içerir ve düzenlenemez.

Kendin dene

require_relative 'standard'
require_relative 'express'
require_relative 'pickup'
require_relative 'shipping_calculator'

# Sağlanan girdi/çıktı kodu: olduğu gibi bırakın
input = []
while (line = gets)
  input << line.chomp
end
strategies = { "standard" => Standard, "express" => Express, "pickup" => Pickup }
calc = ShippingCalculator.new(Standard.new)
input.each do |line|
  cmd, arg = line.split
  if cmd == "use"
    calc.strategy = strategies[arg].new
  else
    puts calc.quote(arg.to_f)
  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