|
| 1 | +--- |
| 2 | +title: Acyclic Visitor |
| 3 | +category: Behavioral |
| 4 | +language: it |
| 5 | +tag: |
| 6 | + - Extensibility |
| 7 | +--- |
| 8 | + |
| 9 | +## Intento |
| 10 | + |
| 11 | +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. |
| 12 | + |
| 13 | +## Spiegazione |
| 14 | + |
| 15 | +Esempio del mondo reale |
| 16 | + |
| 17 | +> 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). |
| 18 | +
|
| 19 | +In parole semplici |
| 20 | + |
| 21 | +> L'Acyclic Visitor consente di aggiungere funzioni alle gerarchie di classi esistenti senza modificarle. |
| 22 | +
|
| 23 | +[WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor) dice |
| 24 | + |
| 25 | +>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)._ |
| 26 | +
|
| 27 | +**Esempio di codice** |
| 28 | + |
| 29 | +Ecco la gerarchia delle classi `Modem`. |
| 30 | + |
| 31 | +```java |
| 32 | +public abstract class Modem { |
| 33 | + public abstract void accept(ModemVisitor modemVisitor); |
| 34 | +} |
| 35 | + |
| 36 | +public class Zoom extends Modem { |
| 37 | + ... |
| 38 | + @Override |
| 39 | + public void accept(ModemVisitor modemVisitor) { |
| 40 | + if (modemVisitor instanceof ZoomVisitor) { |
| 41 | + ((ZoomVisitor) modemVisitor).visit(this); |
| 42 | + } else { |
| 43 | + LOGGER.info("Only ZoomVisitor is allowed to visit Zoom modem"); |
| 44 | + } |
| 45 | + } |
| 46 | +} |
| 47 | + |
| 48 | +public class Hayes extends Modem { |
| 49 | + ... |
| 50 | + @Override |
| 51 | + public void accept(ModemVisitor modemVisitor) { |
| 52 | + if (modemVisitor instanceof HayesVisitor) { |
| 53 | + ((HayesVisitor) modemVisitor).visit(this); |
| 54 | + } else { |
| 55 | + LOGGER.info("Only HayesVisitor is allowed to visit Hayes modem"); |
| 56 | + } |
| 57 | + } |
| 58 | +} |
| 59 | +``` |
| 60 | + |
| 61 | + |
| 62 | +Successivamente introduciamo la gerarchia delle classi `ModemVisitor`. |
| 63 | + |
| 64 | +```java |
| 65 | +public interface ModemVisitor { |
| 66 | +} |
| 67 | + |
| 68 | +public interface HayesVisitor extends ModemVisitor { |
| 69 | + void visit(Hayes hayes); |
| 70 | +} |
| 71 | + |
| 72 | +public interface ZoomVisitor extends ModemVisitor { |
| 73 | + void visit(Zoom zoom); |
| 74 | +} |
| 75 | + |
| 76 | +public interface AllModemVisitor extends ZoomVisitor, HayesVisitor { |
| 77 | +} |
| 78 | + |
| 79 | +public class ConfigureForDosVisitor implements AllModemVisitor { |
| 80 | + ... |
| 81 | + @Override |
| 82 | + public void visit(Hayes hayes) { |
| 83 | + LOGGER.info(hayes + " used with Dos configurator."); |
| 84 | + } |
| 85 | + @Override |
| 86 | + public void visit(Zoom zoom) { |
| 87 | + LOGGER.info(zoom + " used with Dos configurator."); |
| 88 | + } |
| 89 | +} |
| 90 | + |
| 91 | +public class ConfigureForUnixVisitor implements ZoomVisitor { |
| 92 | + ... |
| 93 | + @Override |
| 94 | + public void visit(Zoom zoom) { |
| 95 | + LOGGER.info(zoom + " used with Unix configurator."); |
| 96 | + } |
| 97 | +} |
| 98 | +``` |
| 99 | + |
| 100 | +Infine, ecco i visitatori in azione. |
| 101 | + |
| 102 | +```java |
| 103 | + var conUnix = new ConfigureForUnixVisitor(); |
| 104 | + var conDos = new ConfigureForDosVisitor(); |
| 105 | + var zoom = new Zoom(); |
| 106 | + var hayes = new Hayes(); |
| 107 | + hayes.accept(conDos); |
| 108 | + zoom.accept(conDos); |
| 109 | + hayes.accept(conUnix); |
| 110 | + zoom.accept(conUnix); |
| 111 | +``` |
| 112 | + |
| 113 | +Output del programma: |
| 114 | + |
| 115 | +``` |
| 116 | + // Hayes modem used with Dos configurator. |
| 117 | + // Zoom modem used with Dos configurator. |
| 118 | + // Only HayesVisitor is allowed to visit Hayes modem |
| 119 | + // Zoom modem used with Unix configurator. |
| 120 | +``` |
| 121 | + |
| 122 | +## Diagramma delle classi |
| 123 | + |
| 124 | + |
| 125 | + |
| 126 | +## Applicabilità |
| 127 | + |
| 128 | +Questo pattern può essere utilizzato nei seguenti casi: |
| 129 | + |
| 130 | +* Quando è necessario aggiungere una nuova funzione a una gerarchia esistente senza la necessità di modificarla o influenzarla. |
| 131 | +* Quando ci sono funzioni che operano su una gerarchia, ma che non appartengono alla gerarchia stessa, ad esempio, il problema di ConfigureForDOS / ConfigureForUnix / ConfigureForX. |
| 132 | +* Quando è necessario eseguire operazioni molto diverse su un oggetto a seconda del suo tipo. |
| 133 | +* Quando la gerarchia delle classi visitate sarà frequentemente estesa con nuovi derivati dalla classe Element. |
| 134 | +* Quando la ricompilazione, il relinking, il ritestare o la ridistribuzione dei derivati da Element è molto costoso. |
| 135 | + |
| 136 | +## Tutorial |
| 137 | + |
| 138 | +* [Acyclic Visitor Pattern Example](https://codecrafter.blogspot.com/2012/12/the-acyclic-visitor-pattern.html) |
| 139 | + |
| 140 | +## Conseguenze |
| 141 | + |
| 142 | +Aspetti positivi: |
| 143 | + |
| 144 | +* Assenza di cicli di dipendenza tra le gerarchie di classi. |
| 145 | +* Non è necessario ricompilare tutti i visitatori se se ne aggiunge uno nuovo. |
| 146 | +* Non causa errori di compilazione nei visitatori esistenti se la gerarchia delle classi ha un nuovo membro. |
| 147 | + |
| 148 | +Aspetti negativi: |
| 149 | + |
| 150 | +* 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. |
| 151 | +* Deve essere creata una gerarchia parallela di visitatori per tutti i membri della gerarchia di classi visitabili. |
| 152 | + |
| 153 | +## Pattern correlati |
| 154 | + |
| 155 | +* [Visitor Pattern](https://java-design-patterns.com/patterns/visitor/) |
| 156 | + |
| 157 | +## Collegamenti esterni |
| 158 | + |
| 159 | +* [Acyclic Visitor by Robert C. Martin](http://condor.depaul.edu/dmumaugh/OOT/Design-Principles/acv.pdf) |
| 160 | +* [Acyclic Visitor in WikiWikiWeb](https://wiki.c2.com/?AcyclicVisitor) |
0 commit comments