2008-09-04 2 views
3

Comme un exercice pour moi-même, je traduisais un exemple de programme en plusieurs langues. A partir de C#, j'avais une interface visiteur-modèle comme ceci:manière préférée d'implémenter le modèle de visiteur dans les langages dynamiques?

interface Visitor 
    { 
     void Accept(Bedroom x); 
     void Accept(Bathroom x); 
     void Accept(Kitchen x); 
     void Accept(LivingRoom x); 
    } 

Déplacement à ruby ​​(ou python, ou autre), je ne se dépêche du compilateur en fonction du type. Devrais-je faire l'expédition dans 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 l'envoi dans les différents specializaions de la pièce:

class Bathroom<Room 
    def initialize(name) 
    super(name) 
    end 
    def accept(visitor) 
    visitor.acceptBathroom(self) 
    end 
end 

Ou est-il un autre idiome préféré qui est utilisé dans les langages dynamiques?

Répondre

3

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 pièces augmente; ce dernier est plus difficile à mesure que le nombre de types de nettoyeurs augmente.

Dans Ruby, vous pouvez essayer

def accept(x) 
    send "accept#{x.class}".to_sym, x 
end 

PS: pas toutes langues typées dynamiquement ne parviennent pas à faire l'envoi en fonction du type; certains peuvent déduire le type, ou à défaut, peuvent utiliser la distribution forcée pour choisir la bonne méthode parmi les options surchargées.

3

Je voudrais aller avec la deuxième version. Le premier ressemble au genre d'odeur de code que le Visiteur est supposé résoudre: les longues instructions if-else-if ou switch-case.

Questions connexes