Menu
CoddyTech

Pola Strategy

Termasuk bagian Pemrograman Berorientasi Objek dalam perjalanan Ruby di Coddy. Pelajaran 45 dari 57.

Pola strategy menempatkan satu bagian algoritma ke dalam object tersendiri dan memungkinkan object utama mendelegasikan tugas kepadanya. Mengganti strategy akan mengubah perilaku tanpa mengubah class utama:

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

Output:

8.0
21

Strategi-strategi ini hanya berbagi nama method, jadi object apa pun yang memiliki cost bisa digunakan: duck typing lagi. Menambahkan cara baru untuk mengirim berarti menambahkan satu class, bukan cabang lain di dalam Shipment:

class Pickup
  def cost(_kg)
    0
  end
end

shipment.strategy = Pickup.new     # Shipment tetap sama

Di Ruby, strategi sering kali berupa lambda. Apa pun yang merespons call dapat disimpan dan dipanggil, baik itu lambda, object method, maupun object dari class buatanmu sendiri:

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)

Output:

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

Pilih strategi daripada subclass ketika satu object harus mengubah perilakunya saat program berjalan, atau ketika variasinya hanya satu langkah. Subclass menetapkan perilaku untuk seluruh masa hidup object:

# subclassing: ditetapkan saat dibuat
ExpressShipment.new(2)

# strategy: dapat diubah nanti
shipment = Shipment.new(2, Standard.new)
shipment.strategy = Express.new
challenge icon

Tantangan

Mudah

Lengkapi strategi pengiriman dan ShippingCalculator. Standard#cost(kg) adalah 5 ditambah 1.50 per kg, Express#cost(kg) adalah 15 ditambah 3 per kg, dan Pickup#cost(kg) adalah 0. Calculator dibuat dengan sebuah strategi, bisa mengganti strategi itu dengan strategy=, dan quote(kg) mengembalikan 2.5 kg by Express: 22.50, menggunakan nama class strategi tersebut.

Kode yang disediakan dimulai dengan Standard dan membaca perintah use express, use pickup, use standard atau quote 2.5, lalu mencetak setiap kutipan.

Tuliskan kodemu di standard.rb, express.rb, pickup.rb, dan shipping_calculator.rb. main.rb berisi kode input/output yang disediakan dan tidak boleh diedit.

Coba sendiri

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

# Kode input/output yang disediakan: biarkan apa adanya
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 iconUji dirimu

Pelajaran ini berisi kuis singkat. Mulai pelajarannya untuk menjawab kuis dan melacak progresmu.

Semua pelajaran di Pemrograman Berorientasi Objek

Latihan sendiri: Compiler Ruby online