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:
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:
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 )
.