web-dev-qa-db-fra.com

Modèle de visiteur: quel est le point de la méthode `Accepter`?

J'essaie de bien comprendre le modèle de visiteur. Ce que j'ai appris jusqu'à présent (corrigez-moi si je me trompe) est:

  • Il s'agit d'ajouter des opérations aux classes, sans modifier le code source de ces classes. Ou mettre un autre moyen, plier le OOP Approche pour avoir des fonctions et des structures de données séparées.
  • C'est un malentendu courant que cela a à voir avec des hiérarchies d'objets (bien qu'elle puisse être très utile dans ce cas).

Je pense que je l'obtiens, mais il y a une chose qui me semble inutile, et c'est la méthode accept dans les classes "à visiter". Mettons un petit exemple en Java. Premièrement, la hiérarchie de la classe à être enrichie d'opérations, mais elle ne doit pas être modifiée:

interface Animal {
    void accept(AnimalVisitor visitor);
}

class Dog implements Animal {
    void accept(AnimalVisitor visitor) {
        visitor.visitDog(this);
    }    
}

class Cat implements Animal {
    void accept(AnimalVisitor visitor) {
        visitor.visitCat(this);
    }    
}

Ensuite, l'interface visiteur et une mise en oeuvre factice de cette interface, représentant une opération pour faire du son.

interface AnimalVisitor {
    // These methods could be just called "visit" and rely on overloading,
    void visitDog(Dog dog);
    void visitCat(Cat cat);
}

class MakeSoundVisitor implements AnimalVisitor {
    void visitDog(Dog dog) {
        // In a real case you'd obviously do something with the dog object
        System.out.println("bark! bark bark!!");
    }

    void visitCat(Cat cat) {
        System.out.println("meow meeeoooww!!");
    }
}

Et puis une utilisation de tout cela serait:

var makeSoundVisitor = new MakeSoundVisitor();
var cat = new Cat();
var dog = new Dog();

cat.accept(makeSoundVisitor);
dog.accept(makeSoundVisitor);

Mais je ne vois vraiment pas le point de ce accept appel. Si vous avez visité le visiteur et les objets à visiter, pourquoi ne pas simplement passer ces objets directement sur le visiteur et éviter l'indirection? Vous pouvez même vous débarrasser de la méthode accept sur l'interface Animal. Quelque chose comme ça:

var makeSoundVisitor = new MakeSoundVisitor();
var cat = new Cat();
var dog = new Dog();

makeSoundVisitor.visitCat(cat);
makeSoundVisitor.visitDog(dog);

Sources:

25
bgusach

accept est un moyen de type statique de type pour permettre une if-échelle basée sur le type de quelque chose.

if ( thing instanceof Foo ) {
    Foo foo = ( Foo )thing;
    BODY1
} else if ( thing instanceof Bar ) {
    Bar bar = ( Bar )thing;
    BODY2
} else if ...

devient

new ThingVisitor() {
    void ifThingInstanceOfFoo( Foo foo ) {
        BODY1
    }
    void elseIfThingInstanceOfBar( Bar bar ) {
        BODY2
    }
    ...
}

La seule façon qui peut fonctionner et ne pas compter sur le casting est si la "mise en œuvre" de if, la sélection de laquelle la méthode visiteur à appeler, vit dans une fonction polymorphe accept( Thing thing ).

0
Judge Mental