الطريقة المفضلة لتنفيذ نمط الزائر باللغات الديناميكية؟
-
09-06-2019 - |
سؤال
وكتمرين لنفسي، كنت أقوم بترجمة نموذج لبرنامج إلى لغات مختلفة.بدءًا من لغة C#، كانت لدي واجهة بنمط الزائر كما يلي:
interface Visitor
{
void Accept(Bedroom x);
void Accept(Bathroom x);
void Accept(Kitchen x);
void Accept(LivingRoom x);
}
بالانتقال إلى روبي (أو بايثون، أو أي شيء آخر)، لم أعد أتلقى إرسالًا من المترجم بناءً على النوع.هل يجب أن أقوم بالإرسال في الزائر نفسه؟
class Cleaner
def accept(x)
acceptBedroom(x) if Bedroom === x
acceptBathroom(x) if Bathroom === x
acceptKitchen(x) if Kitchen===x
acceptLivingRoom(x) if LivingRoom===x
end
...
أم يجب أن أقوم بالإرسال في تخصصات الغرفة المختلفة:
class Bathroom<Room
def initialize(name)
super(name)
end
def accept(visitor)
visitor.acceptBathroom(self)
end
end
أم أن هناك لغة مفضلة أخرى تستخدم في اللغات الديناميكية؟
المحلول
توصيتي هي استخدام النهج السابق.هناك إيجابيات وسلبيات لكل نهج.يصعب الحفاظ على النوع الأول مع تزايد عدد أنواع الغرف؛الأخير أصعب مع تزايد عدد أنواع المنظف.
في روبي، يمكنك أن تجرب
def accept(x)
send "accept#{x.class}".to_sym, x
end
ملاحظة:ليست كل اللغات المكتوبة ديناميكيًا غير قادرة على القيام بالإرسال بناءً على النوع؛يمكن للبعض استنتاج النوع، أو في حالة الفشل في ذلك، يمكن استخدام الاختيار القسري لاختيار الطريقة المناسبة من بين الخيارات المثقلة.
نصائح أخرى
سأذهب مع الإصدار الثاني.الأول يشبه نوع رائحة الكود الذي من المفترض أن يحله الزائر:عبارات if-else-if الطويلة أو حالة التبديل.