نمط المزيّن
جزء من قسم البرمجة كائنية التوجه في رحلة Ruby على Coddy. الدرس 47 من 57.
نمط decorator يغلّف كائنًا داخل كائن آخر له الواجهة نفسها، مما يضيف شيئًا قبل تمرير الاستدعاء أو بعده. يمكن تكديس الـ decorators بأي ترتيب:
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)الناتج:
coffee, milk, milk: 3.00يخزّن كل مُزيّن الكائن المُغلَّف ويمرّر إليه، لذا يمكن لفئة أساسية مشتركة أن تتولى هذا الجزء. بعد ذلك يتجاوز كل مُزيّن ملموس فقط ما يغيّره:
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)الناتج:
coffee, sugar: 2.20تُمرِّر مكتبة SimpleDelegator القياسية (require 'delegate') كل طريقة لا تعرّفها إلى الكائن المُغلَّف، مما يُبقي الزخارف قصيرة عندما تكون الواجهة كبيرة:
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")الناتج:
HELLO!
5
trueتضيف المُزخرفات سلوكًا إلى كائنات منفردة أثناء وقت التشغيل، ويمكن دمجها بحرية. أما مع الفئات الفرعية، فستحتاج كل تركيبة مثل MilkSugarCoffee إلى فئة خاصة بها:
Sugar.new(Milk.new(Coffee.new)) # أي تركيبة، بأي ترتيب
Whip.new(Sugar.new(Coffee.new))
# مع الفئات الفرعية: MilkCoffee, SugarCoffee, MilkSugarCoffee, ...التحدي
سهلأكمل مزينات القهوة. تكلفة Coffee هي 2.00 ووصفها هو coffee. تضيف Milk مقدار 0.50 و, milk، وتضيف Sugar مقدار 0.20 و, sugar، وتضيف Whip مقدار 0.70 و, whip. تشترك المزينات الثلاثة في الصنف الأساسي Extra، الذي يخزّن المشروب المُغلَّف ويمرّر cost وdescription؛ ويستخدم كل صنف فرعي super.
كل سطر إدخال هو طلب مثل milk sugar. يغلّف الكود المزوَّد كائن Coffee جديدًا بالمزينات حسب ذلك الترتيب، ثم يطبع coffee, milk, sugar: 2.70.
ضع كودك في coffee.rb وextra.rb وmilk.rb وsugar.rb وwhip.rb. يحتوي main.rb على كود الإدخال/الإخراج المزوَّد، ولا يمكن تعديله.
جرّب بنفسك
require_relative 'coffee'
require_relative 'extra'
require_relative 'milk'
require_relative 'sugar'
require_relative 'whip'
# كود الإدخال/الإخراج المُزوَّد: أبقِه كما هو
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
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1الفئات والكائنات
العمل مع الملفاتتعريف الفئاتمتغيرات النسخةالأساليب و selfto_s و inspectمراجعة - بطاقة المكتبة7تعدد الأشكال والكتابة بأسلوب البطة
تعدد الأشكالالكتابة بأسلوب البطةالأساليب المجردةالحالات والفئاتمراجعة - طرق الدفع3أساليب ومتغيرات الأصناف
أساليب الأصنافمتغيرات كائنات الأصنافالثوابتأساليب الإنشاءمراجعة - رموز القسائمتدرّب بنفسك: مترجم Ruby عبر الإنترنت