¿Forma preferida de implementar el patrón de visitante en lenguajes dinámicos?
-
09-06-2019 - |
Pregunta
Como ejercicio para mí, estuve traduciendo un programa de muestra a varios idiomas.Comenzando en C#, tenía una interfaz de patrón de visitante como esta:
interface Visitor
{
void Accept(Bedroom x);
void Accept(Bathroom x);
void Accept(Kitchen x);
void Accept(LivingRoom x);
}
Al pasar a Ruby (o Python, o lo que sea), ya no recibo el envío del compilador según el tipo.¿Debo hacer el despacho en el propio visitante?
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
...
O debería hacer el despacho en las diferentes especializaciones de la sala:
class Bathroom<Room
def initialize(name)
super(name)
end
def accept(visitor)
visitor.acceptBathroom(self)
end
end
¿O existe otro modismo preferido que se utiliza en lenguajes dinámicos?
Solución
Mi recomendación es utilizar el primer enfoque.Hay ventajas y desventajas para cada enfoque.El primero es más difícil de mantener a medida que crece el número de tipos de habitaciones;este último es más difícil a medida que crece el número de tipos de limpiadores.
En Ruby, puedes probar
def accept(x)
send "accept#{x.class}".to_sym, x
end
PD:no todos los lenguajes escritos dinámicamente no pueden realizar el envío según el tipo;algunos pueden inferir el tipo o, en su defecto, pueden utilizar la conversión forzada para elegir el método adecuado entre las opciones sobrecargadas.
Otros consejos
Yo elegiría la segunda versión.El primero parece el tipo de código que se supone que debe resolver el Visitante:declaraciones largas if-else-if o switch-case.