نمط 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، غالبًا ما تكون الاستراتيجية عبارة عن lambda. يمكن تخزين أي شيء يستجيب لـ call واستدعاؤه، سواء أكان lambda أو كائن طريقة أو كائنًا من فئتك الخاصة:
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التحدي
سهلأكمل استراتيجيات الشحن و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
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1الفئات والكائنات
العمل مع الملفاتتعريف الفئاتمتغيرات النسخةالأساليب و selfto_s و inspectمراجعة - بطاقة المكتبة7تعدد الأشكال والكتابة بأسلوب البطة
تعدد الأشكالالكتابة بأسلوب البطةالأساليب المجردةالحالات والفئاتمراجعة - طرق الدفع3أساليب ومتغيرات الأصناف
أساليب الأصنافمتغيرات كائنات الأصنافالثوابتأساليب الإنشاءمراجعة - رموز القسائمتدرّب بنفسك: مترجم Ruby عبر الإنترنت