mirror of
https://github.com/tiennm99/java-design-patterns.git
synced 2026-05-18 15:26:01 +00:00
87a774c9d6
* translate Abstract Document documentation in french * translate Abstract Document documentation in french for issue #2278 * french translation of abstract factory * French translation for active-object * translate Abstract Document documentation in french * translate Abstract Document documentation in french for issue #2278 * french translation of abstract factory * French translation for active-object * tranlate to french: acyclic-visitore, adapter, aggregator-microservice, ambassador, api-gateway, arrange-act-assert, async-method-invocation, balking, bridge.
163 lines
5.0 KiB
Markdown
163 lines
5.0 KiB
Markdown
---
|
|
title: Acyclic Visitor
|
|
category: Behavioral
|
|
language: fr
|
|
tag:
|
|
- Extensibility
|
|
---
|
|
|
|
## Intention
|
|
|
|
Permettre l'ajout de nouvelles fonctions à des hiérarchies de classes existantes sans affecter ces hiérarchies et sans
|
|
créer de cycles de dépendance gênants inhérents au pqtron de conception GoF visitor.
|
|
|
|
## Explication
|
|
|
|
Exemple concret
|
|
|
|
> Nous disposons d'une hiérarchie de classes de modems. Les modems de cette hiérarchie doivent être visités
|
|
> par un algorithme externe basé sur des critères de filtrage (s'agit-il d'un modem compatible Unix ou DOS).
|
|
|
|
En clair
|
|
|
|
> Le visiteur acyclique permet d'ajouter des fonctions à des hiérarchies de classes existantes sans modifier ces dernières.
|
|
|
|
[WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor) dit
|
|
|
|
> Le modèle du visiteur acyclique permet d'ajouter de nouvelles fonctions aux hiérarchies de classes existantes
|
|
> sans affecter ces hiérarchies et sans créer les cycles de dépendance inhérents au patron de conception GangOfFour visitor.
|
|
|
|
**Exemple de Programme**
|
|
|
|
Ci-dessous la hierarchie `Modem`.
|
|
|
|
```java
|
|
public abstract class Modem {
|
|
public abstract void accept(ModemVisitor modemVisitor);
|
|
}
|
|
|
|
public class Zoom extends Modem {
|
|
...
|
|
@Override
|
|
public void accept(ModemVisitor modemVisitor) {
|
|
if (modemVisitor instanceof ZoomVisitor) {
|
|
((ZoomVisitor) modemVisitor).visit(this);
|
|
} else {
|
|
LOGGER.info("Only ZoomVisitor is allowed to visit Zoom modem");
|
|
}
|
|
}
|
|
}
|
|
|
|
public class Hayes extends Modem {
|
|
...
|
|
@Override
|
|
public void accept(ModemVisitor modemVisitor) {
|
|
if (modemVisitor instanceof HayesVisitor) {
|
|
((HayesVisitor) modemVisitor).visit(this);
|
|
} else {
|
|
LOGGER.info("Only HayesVisitor is allowed to visit Hayes modem");
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
Ensuite, nous introduisons la hiérarchie `ModemVisitor`.
|
|
|
|
```java
|
|
public interface ModemVisitor {
|
|
}
|
|
|
|
public interface HayesVisitor extends ModemVisitor {
|
|
void visit(Hayes hayes);
|
|
}
|
|
|
|
public interface ZoomVisitor extends ModemVisitor {
|
|
void visit(Zoom zoom);
|
|
}
|
|
|
|
public interface AllModemVisitor extends ZoomVisitor, HayesVisitor {
|
|
}
|
|
|
|
public class ConfigureForDosVisitor implements AllModemVisitor {
|
|
...
|
|
@Override
|
|
public void visit(Hayes hayes) {
|
|
LOGGER.info(hayes + " used with Dos configurator.");
|
|
}
|
|
@Override
|
|
public void visit(Zoom zoom) {
|
|
LOGGER.info(zoom + " used with Dos configurator.");
|
|
}
|
|
}
|
|
|
|
public class ConfigureForUnixVisitor implements ZoomVisitor {
|
|
...
|
|
@Override
|
|
public void visit(Zoom zoom) {
|
|
LOGGER.info(zoom + " used with Unix configurator.");
|
|
}
|
|
}
|
|
```
|
|
|
|
Enfin, voici les visitors en action.
|
|
|
|
```java
|
|
var conUnix = new ConfigureForUnixVisitor();
|
|
var conDos = new ConfigureForDosVisitor();
|
|
var zoom = new Zoom();
|
|
var hayes = new Hayes();
|
|
hayes.accept(conDos);
|
|
zoom.accept(conDos);
|
|
hayes.accept(conUnix);
|
|
zoom.accept(conUnix);
|
|
```
|
|
|
|
Sortie du programme :
|
|
|
|
```
|
|
// Hayes modem used with Dos configurator.
|
|
// Zoom modem used with Dos configurator.
|
|
// Only HayesVisitor is allowed to visit Hayes modem
|
|
// Zoom modem used with Unix configurator.
|
|
```
|
|
|
|
## Diagramme de classes
|
|
|
|

|
|
|
|
## Application
|
|
|
|
Ce patron de conception peut être utilisé:
|
|
|
|
* Pour ajouter ne nouvelle fonction à une hiérarchie existante sans avoir à modifier ou à affecter cette hiérarchie.
|
|
* Lorsqu'il existe des fonctions qui opèrent sur une hiérarchie, mais qui n'appartiennent pas à la hiérarchie elle-même. Par exemple, le problème ConfigureForDOS / ConfigureForUnix / ConfigureForX.
|
|
* Lorsque vous devez éffectuer des opérations très différentes sur un objet en fonction de son type.
|
|
* Lorsque la hiérarchie des classes visitées sera fréquemment étendue avec de nouveaux dérivés de la classe Element.
|
|
*Lorsque la recompilation, l'interconnexion, le réessai ou la redistribution des dérivés de Element sont très coûteux.
|
|
|
|
## Tutoriel
|
|
|
|
* [Acyclic Visitor Pattern Example](https://codecrafter.blogspot.com/2012/12/the-acyclic-visitor-pattern.html)
|
|
|
|
## Consequences
|
|
|
|
Le bon côté:
|
|
|
|
* Pas de cycles de dépendance entre les hiérarchies de classes.
|
|
* Il n'est pas nécessaire de recompiler tous les visiteurs si un nouveau visiteur est ajouté.
|
|
* Ne provoque pas d'échec de compilation chez les visiteurs existants si la hiérarchie des classes a un nouveau membre.
|
|
|
|
Le mauvais :
|
|
|
|
* viole le [principe de substitution de Liskov](https://java-design-patterns.com/principles/#liskov-substitution-principle) en montrant qu'il peut accepter tous les visiteurs alors qu'il ne s'intéresse en réalité qu'à certains d'entre eux.
|
|
* Une hiérarchie parallèle de visiteurs doit être créée pour tous les membres de la hiérarchie des classes visitables.
|
|
|
|
## Patron de conception associé
|
|
|
|
* [Pqtron de conception Visitor](https://java-design-patterns.com/patterns/visitor/)
|
|
|
|
## Crédits
|
|
|
|
* [Acyclic Visitor by Robert C. Martin](http://condor.depaul.edu/dmumaugh/OOT/Design-Principles/acv.pdf)
|
|
* [Acyclic Visitor in WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor)
|