Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 160 additions & 0 deletions localization/it/acyclic-visitor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
---
title: Acyclic Visitor
category: Behavioral
language: it
tag:
- Extensibility
---

## Intento

Permette di aggiungere nuove funzioni alle gerarchie di classi esistenti senza influire su tali gerarchie e senza creare i cicli di dipendenza problematici che sono intrinseci al pattern Visitor dei GoF.

## Spiegazione

Esempio del mondo reale

> Abbiamo una gerarchia di classi di modem. I modem in questa gerarchia devono essere visitati da un algoritmo esterno basato su criteri di filtraggio (ad esempio, se si tratta di un modem compatibile con Unix o DOS).

In parole semplici

> L'Acyclic Visitor consente di aggiungere funzioni alle gerarchie di classi esistenti senza modificarle.

[WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor) dice

>Il pattern Acyclic Visitor consente di aggiungere nuove funzioni alle gerarchie di classi esistenti senza influire su tali gerarchie e senza creare i cicli di dipendenza che sono intrinseci al pattern Visitor dei Gang of Four. _(Testo tradotto dalla voce Acyclic Visitor da WikiWikiWeb in lingua inglese)._

**Esempio di codice**

Ecco la gerarchia delle classi `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");
}
}
}
```


Successivamente introduciamo la gerarchia delle classi `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.");
}
}
```

Infine, ecco i visitatori in azione.

```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 programma:

```
// 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.
```

## Diagramma delle classi

![alt text](../../../acyclic-visitor/etc/acyclic-visitor.png "Acyclic Visitor")

## Applicabilità

Questo pattern può essere utilizzato nei seguenti casi:

* Quando è necessario aggiungere una nuova funzione a una gerarchia esistente senza la necessità di modificarla o influenzarla.
* Quando ci sono funzioni che operano su una gerarchia, ma che non appartengono alla gerarchia stessa, ad esempio, il problema di ConfigureForDOS / ConfigureForUnix / ConfigureForX.
* Quando è necessario eseguire operazioni molto diverse su un oggetto a seconda del suo tipo.
* Quando la gerarchia delle classi visitate sarà frequentemente estesa con nuovi derivati dalla classe Element.
* Quando la ricompilazione, il relinking, il ritestare o la ridistribuzione dei derivati da Element è molto costoso.

## Tutorial

* [Acyclic Visitor Pattern Example](https://codecrafter.blogspot.com/2012/12/the-acyclic-visitor-pattern.html)

## Conseguenze

Aspetti positivi:

* Assenza di cicli di dipendenza tra le gerarchie di classi.
* Non è necessario ricompilare tutti i visitatori se se ne aggiunge uno nuovo.
* Non causa errori di compilazione nei visitatori esistenti se la gerarchia delle classi ha un nuovo membro.

Aspetti negativi:

* Viola il [Principio di sostituzione di Liskov](https://java-design-patterns.com/principles/#liskov-substitution-principle) mostrando di poter accettare tutti i visitatori ma essendo solo interessato a visitatori specifici.
* Deve essere creata una gerarchia parallela di visitatori per tutti i membri della gerarchia di classi visitabili.

## Pattern correlati

* [Visitor Pattern](https://java-design-patterns.com/patterns/visitor/)

## Collegamenti esterni

* [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)