Menu
CoddyTech

نمط Strategy

جزء من قسم البرمجة كائنية التوجه في رحلة Ruby على Coddy. الدرس 45 من 57.

يضع نمط الاستراتيجية جزءًا من الخوارزمية في كائن مستقل، ويتيح للكائن الرئيسي تفويض العمل إليه. يؤدي تبديل الاستراتيجية إلى تغيير السلوك من دون تغيير الصنف الرئيسي:

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

الناتج:

8.0
21

لا تشترك الاستراتيجيات إلا في اسم طريقة، لذا يعمل أي كائن لديه cost: هذا هو أسلوب الكتابة وفقًا لسلوك الكائن مجددًا. تعني إضافة طريقة جديدة للشحن إضافة صنف واحد، لا فرعًا آخر داخل Shipment:

class Pickup
  def cost(_kg)
    0
  end
end

shipment.strategy = Pickup.new     # يبقى Shipment دون تغيير

في Ruby، تكون الاستراتيجية غالبًا دالة لامبدا. يمكن تخزين أي شيء يستجيب لـ call واستدعاؤه، سواء أكان دالة لامبدا أم كائن طريقة أم كائنًا من صنف خاص بك:

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)

الناتج:

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

اختر الاستراتيجية بدلًا من الفئات الفرعية عندما يلزم أن يغيّر كائنٌ ما سلوكه أثناء تشغيل البرنامج، أو عندما يكون الاختلاف خطوة واحدة. تحدد الفئة الفرعية السلوك طوال حياة الكائن:

# التوريث بالفئات الفرعية: ثابت عند الإنشاء
ExpressShipment.new(2)

# الاستراتيجية: يمكن تغييرها لاحقًا
shipment = Shipment.new(2, Standard.new)
shipment.strategy = Express.new
challenge icon

التحدي

سهل

أكمل استراتيجيات الشحن وShippingCalculator. قيمة Standard#cost(kg) هي 5 زائد 1.50 لكل كغ، وقيمة Express#cost(kg) هي 15 زائد 3 لكل كغ، وقيمة Pickup#cost(kg) هي 0. يُنشأ الحاسوب باستخدام استراتيجية، ويمكن تغييرها باستخدام strategy=، وتُرجع quote(kg) القيمة 2.5 kg by Express: 22.50، مستخدمةً اسم فئة الاستراتيجية.

يبدأ الكود المقدم باستخدام Standard ويقرأ الأوامر use express أو use pickup أو use standard أو quote 2.5، ويطبع كل عرض سعر.

ضع الكود الخاص بك في standard.rb وexpress.rb وpickup.rb وshipping_calculator.rb. يحتوي main.rb على كود الإدخال والإخراج المقدم، ولا يمكن تعديله.

جرّب بنفسك

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

# كود الإدخال والإخراج المقدَّم: اتركه كما هو
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 iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم Ruby عبر الإنترنت