предпочтительный способ реализации шаблона посетителя на динамических языках?
-
09-06-2019 - |
Вопрос
В качестве упражнения для себя я переводил пример программы на разные языки.Начиная с C #, у меня был интерфейс с шаблоном посетителя, подобный следующему:
interface Visitor
{
void Accept(Bedroom x);
void Accept(Bathroom x);
void Accept(Kitchen x);
void Accept(LivingRoom x);
}
Переходя на ruby (или python, или что-то еще), я больше не получаю отправку от компилятора на основе типа.Должен ли я выполнить отправку в самом посетителе?
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
Или есть другая предпочтительная идиома, которая используется в динамических языках?
Решение
Моя рекомендация состоит в том, чтобы использовать первый подход.У каждого подхода есть свои плюсы и минусы.Первое сложнее поддерживать по мере роста числа типов номеров;последнее сложнее по мере роста числа Более чистых типов.
В Ruby вы могли бы попробовать
def accept(x)
send "accept#{x.class}".to_sym, x
end
PS:не все языки с динамической типизацией не могут выполнять отправку на основе типа;некоторые могут определить тип, или, в противном случае, могут использовать принудительное приведение, чтобы выбрать правильный метод среди перегруженных опций.
Другие советы
Я бы предпочел вторую версию.Первый из них выглядит как проблема с запахом кода, которую должен решить посетитель:длинные операторы if-else-if или switch-case.