moyen préféré d'implémenter un modèle de visiteur dans des langages dynamiques ?
-
09-06-2019 - |
Question
Comme exercice pour moi-même, je traduisais un exemple de programme dans différentes langues.À partir de C#, j'avais une interface de modèle de visiteur comme celle-ci :
interface Visitor
{
void Accept(Bedroom x);
void Accept(Bathroom x);
void Accept(Kitchen x);
void Accept(LivingRoom x);
}
En passant à Ruby (ou Python, ou autre), je ne reçois plus de répartition du compilateur en fonction du type.Dois-je effectuer l'envoi chez le visiteur lui-même ?
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
...
Ou dois-je faire le dispatch dans les différentes spécialisations de la salle :
class Bathroom<Room
def initialize(name)
super(name)
end
def accept(visitor)
visitor.acceptBathroom(self)
end
end
Ou existe-t-il un autre idiome préféré utilisé dans les langages dynamiques ?
La solution
Ma recommandation est d’utiliser la première approche.Il y a des avantages et des inconvénients pour chaque approche.Le premier est plus difficile à maintenir à mesure que le nombre de types de chambres augmente ;ce dernier est plus difficile à mesure que le nombre de types de nettoyeurs augmente.
En Ruby, vous pouvez essayer
def accept(x)
send "accept#{x.class}".to_sym, x
end
PS :Tous les langages typés dynamiquement ne sont pas incapables d'effectuer une répartition en fonction du type ;certains peuvent déduire le type, ou à défaut, peuvent utiliser le casting forcé pour choisir la méthode appropriée parmi les options surchargées.
Autres conseils
J'opterais pour la deuxième version.Le premier ressemble au genre d’odeur de code que Visitor est censé résoudre :longues instructions if-else-if ou switch-case.