mirror of
https://github.com/tiennm99/java-design-patterns.git
synced 2026-05-18 05:25:45 +00:00
dc7495e8bd
* Typo corrections * bridge pattern translated to spanish * builder pattern translated to spanish * context-object pattern translated to spanish * converter pattern translated to spanish * dependency injection pattern translated to spanish * factory pattern translated to spanish * factory-kit pattern translated to spanish * factory-method pattern translated to spanish * monostate pattern translated to spanish * multiton pattern translated to spanish * object mother pattern translated to spanish * object pool pattern translated to spanish * property pattern translated to spanish * prototype pattern translated to spanish * registry pattern translated to spanish * step builder pattern translated to spanish * value object pattern translated to spanish * typo corrections and resources urls refactor * grammar corrections * Add image to each pattern --------- Co-authored-by: luismateoh <luismateohm@gmail.com> Co-authored-by: luis.hincapie <luis.hincapie@blankfactor.com>
160 lines
4.7 KiB
Markdown
160 lines
4.7 KiB
Markdown
---
|
|
title: Acyclic Visitor
|
|
category: Behavioral
|
|
language: es
|
|
tag:
|
|
- Extensibility
|
|
---
|
|
|
|
## Propósito
|
|
|
|
Permitir añadir nuevas funciones a jerarquías de clases existentes sin que estas se vean afectadas, y sin crear los problemáticos círculos de dependencias que son inherentes al patrón GoF (Gang of Four) Visitor.
|
|
|
|
## Explicación
|
|
|
|
Ejemplo del mundo real
|
|
|
|
> Tenemos una jerarquía de clases módem. Los modems de esta jerarquía deben ser visitados por un algoritmo externo basándose en unos filtros (el módem es compatible con Unix o DOS).
|
|
|
|
En otras palabras
|
|
|
|
> Acyclic Visitor permite añadir funciones a jerarquías de clases existentes sin modificarlas.
|
|
|
|
[WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor) dice
|
|
|
|
> El patrón Acyclic Visitor permite que nuevas funciones sean añadidas a jerarquías de clases existentes sin afectar a las mismas, y sin crear los círculos de dependencias que son inherentes al patrón de visitante (Visitor Pattern) de GangOfFour.
|
|
|
|
**Ejemplo Programático**
|
|
|
|
Aquí tenemos la jerarquía `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");
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
Después tenemos la jerarquía `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.");
|
|
}
|
|
}
|
|
```
|
|
|
|
Finalmente, aquí están los "visitors" en acción.
|
|
|
|
```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);
|
|
```
|
|
|
|
Output del programa:
|
|
|
|
```
|
|
// 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.
|
|
```
|
|
|
|
## Diagrama de clases
|
|
|
|

|
|
|
|
## Aplicación
|
|
|
|
Este patrón puede ser usado:
|
|
|
|
* Cuando necesitas añadir una nueva función a una jerarquía de clases sin que esta se vea afectada o alterada.
|
|
* Cuando hay funciones que operan sobre la jerarquía, pero no pertenecen a la jerarquía como tal. Las clases ConfigureForDOS / ConfigureForUnix / ConfigureForX por ejemplo.
|
|
* Cuando necesitas ejecutar operaciones muy diferentes en un objeto dependiendo de su tipo.
|
|
* Cuando la jerarquía visitada va a ser frecuentemente extendida con derivados de la clase elemento.
|
|
* Cuando el proceso de volver a compilar, enlazar, probar o distribuir los derivados de la clase elemento es muy pesado.
|
|
|
|
## Tutoriales
|
|
|
|
* [Acyclic Visitor Pattern Example](https://codecrafter.blogspot.com/2012/12/the-acyclic-visitor-pattern.html)
|
|
|
|
## Consecuencias
|
|
|
|
Buenas:
|
|
|
|
* No hay círculos de dependencias entre las jerarquías.
|
|
* No es necesario compilar todos los visitantes si se añade uno nuevo.
|
|
* No provoca errores de compilación en visitantes existentes si la jerarquía tiene un nuevo miembro.
|
|
|
|
Malas:
|
|
|
|
* Viola el [Principio de sustitución de Liskov](https://java-design-patterns.com/principles/#liskov-substitution-principle) al mostrar que puede aceptar todos los visitantes solamente estando interesado en uno en particular.
|
|
* Hay que crear una jerarquía de visitantes paralela para todos los miembros de una jerarquía visitable.
|
|
|
|
## Patrones relacionados
|
|
|
|
* [Visitor Pattern](https://java-design-patterns.com/patterns/visitor/)
|
|
|
|
## Créditos
|
|
|
|
* [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)
|